使用 Web API 时 JSON 数据中的额外项目

Extra items in JSON data when using Web API

我对来自 Web API 服务的 JSON 数据有疑问。

在常规 Web API 控制器中,我得到下面给出的结果。

[
  {
    "title": "başlık",
    "description": "Tanımlama",
    "creationTime": "2018-01-15T17:20:06.9801797",
    "state": 0,
    "assignedPersonId": "afd46520-521d-4945-a4ee-083893e1d14c",
    "assignedPersonName": "derya",
    "id": 2
  },
  {
    "title": "title",
    "description": "description",
    "creationTime": "2018-01-15T17:17:26.5161288",
    "state": 0,
    "assignedPersonId": null,
    "assignedPersonName": null,
    "id": 1
  }
]

但是当使用 ASP.NET 样板基础架构时,我得到的数据与:

{
  "result": {
    "items": [
      {
        "title": "başlık",
        "description": "Tanımlama",
        "creationTime": "2018-01-15T17:20:06.9801797",
        "state": 0,
        "assignedPersonId": "afd46520-521d-4945-a4ee-083893e1d14c",
        "assignedPersonName": "derya",
        "id": 2
      },
      {
        "title": "title",
        "description": "description",
        "creationTime": "2018-01-15T17:17:26.5161288",
        "state": 0,
        "assignedPersonId": null,
        "assignedPersonName": null,
        "id": 1
      }
    ]
  },
  "targetUrl": null,
  "success": true,
  "error": null,
  "unAuthorizedRequest": false,
  "__abp": true
}

看起来实际的原始数据嵌套在一个外部数据结构中。因此,像下面这样的反序列化不起作用。

List<Class1> data = JsonConvert.DeserializeObject<List<Class1>>(JSONString); 

而且我必须在 JSONString 上管理一些字符串操作。

我是不是做错了什么?提前致谢。

来自 WrapResult and DontWrapResult Attributes 上的文档:

You can control wrapping using WrapResult and DontWrapResult attributes for an action or all actions of a controller.

ASP.NET MVC Controllers

ASP.NET Boilerplate wraps ASP.NET MVC action results by default if return type is JsonResult (or Task<JsonResult> for async actions). You can change this by using WrapResult attribute as shown below:

public class PeopleController : AbpController
{
    [HttpPost]
    [WrapResult(WrapOnSuccess = false, WrapOnError = false)]
    public JsonResult SavePerson(SavePersonModel person)
    {
        // TODO: save new person to database and return new person's id
        return Json(new {PersonId = 42});
    }
}

As a shortcut, we can just use [DontWrapResult] which is identical for this example.

You can change this default behaviour from startup configuration.

这不仅适用于 ASP.NET MVC 控制器,还适用于 ASP.NET Web API 控制器、动态 Web API 层和 ASP.NET 核心控制器.

谢谢@Aaron 提供了如此干净利落的答案。

@Inanc,如果你能将这个 JSON 响应映射到下面提到的 class 也。

JSON:

{
  "result": {
    "items": [
      {
        "title": "başlık",
        "description": "Tanımlama",
        "creationTime": "2018-01-15T17:20:06.9801797",
        "state": 0,
        "assignedPersonId": "afd46520-521d-4945-a4ee-083893e1d14c",
        "assignedPersonName": "derya",
        "id": 2
      },
      {
        "title": "title",
        "description": "description",
        "creationTime": "2018-01-15T17:17:26.5161288",
        "state": 0,
        "assignedPersonId": null,
        "assignedPersonName": null,
        "id": 1
      }
    ]
  },
  "targetUrl": null,
  "success": true,
  "error": null,
  "unAuthorizedRequest": false,
  "__abp": true
}

代码:

public class Item
{
    public string title { get; set; }
    public string description { get; set; }
    public DateTime creationTime { get; set; }
    public int state { get; set; }
    public string assignedPersonId { get; set; }
    public string assignedPersonName { get; set; }
    public int id { get; set; }
}

public class Result
{
    public List<Item> items { get; set; }
}

public class RootObject
{
    public Result result { get; set; }
    public object targetUrl { get; set; }
    public bool success { get; set; }
    public object error { get; set; }
    public bool unAuthorizedRequest { get; set; }
    public bool __abp { get; set; }
}

反序列化代码:

List<RootObject> data = JsonConvert.DeserializeObject<List<RootObject>>(JSONString); 

将这两行添加到 Web.Core 项目模块 (<ProjectName>WebCoreModuleModule.cs) 的 PreInitialize() 方法中:docs

Configuration.Modules.AbpAspNetCore().DefaultWrapResultAttribute.WrapOnError = false;
Configuration.Modules.AbpAspNetCore().DefaultWrapResultAttribute.WrapOnSuccess = false;