【问题标题】:Return JsonResult from web api without its properties从没有属性的 web api 返回 JsonResult
【发布时间】:2014-10-14 00:10:42
【问题描述】:

我有一个 Web API 控制器,从那里我从一个动作返回一个对象作为 JSON。

我是这样做的:

public ActionResult GetAllNotificationSettings()
{
    var result = new List<ListItems>();
    // Filling the list with data here...

    // Then I return the list
    return new JsonResult { Data = result };
}

但是通过这种方式,包括其Data 属性的 JsonResult 对象被序列化为 JSON。所以我最终由操作返回的 JSON 如下所示:

{
    "ContentEncoding": null,
    "ContentType": null,
    "Data": {
        "ListItems": [
            {
                "ListId": 2,
                "Name": "John Doe"
            },
            {
                "ListId": 3,
                "Name": "Jane Doe"
            },
        ]
    },
    "JsonRequestBehavior": 1,
    "MaxJsonLength": null,
    "RecursionLimit": null
}

我无法序列化这个 JSON 字符串,因为 JsonResult 对象向它添加了各种其他属性。我只对ListItems 感兴趣,没有别的。但它会自动添加如下内容:ContentTypeMaxJsonLength 等...

现在这对我不起作用,因为 JSON 字符串中的所有其他属性...

var myList = JsonConvert.DeserializeObject<List<ListItems>>(jsonString);

有没有办法从操作中发送一个 JSON 对象,这样它就不会添加我不需要的所有属性?

【问题讨论】:

  • 这看起来不像 web api 而是普通的 mvc。
  • @DanielA.White 嗯,它是 Web API。我的控制器也从它扩展而来。
  • 你不应该使用ActionResult/JsonResult
  • 啊,我明白了,那可以解释问题了:p
  • 要在“常规控制器”中返回 json 数据,您的方法必须返回 new Json,请参阅:stackoverflow.com/a/227638/19046

标签: c# asp.net-mvc asp.net-mvc-4 asp.net-web-api json.net


【解决方案1】:
return JsonConvert.SerializeObject(images.ToList(), Formatting.None, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.None, ReferenceLoopHandling = ReferenceLoopHandling.Ignore });


using Newtonsoft.Json;

【讨论】:

    【解决方案2】:

    我遇到了类似的问题(不同之处在于我想返回一个已经转换为 json 字符串的对象,而我的控制器 get 返回一个 IHttpActionResult

    这是我解决它的方法。首先我声明了一个实用程序类

    public class RawJsonActionResult : IHttpActionResult
    {
        private readonly string _jsonString;
    
        public RawJsonActionResult(string jsonString)
        {
            _jsonString = jsonString;
        }
    
        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var content = new StringContent(_jsonString);
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = content };
            return Task.FromResult(response);
        }
    }
    

    然后可以在您的控制器中使用此类。这是一个简单的例子

    public IHttpActionResult Get()
    {
        var jsonString = "{\"id\":1,\"name\":\"a small object\" }";
        return new RawJsonActionResult(jsonString);
    }
    

    【讨论】:

      【解决方案3】:

      作为一个使用 ASP.NET API 大约 3 年的人,我建议改为返回 HttpResponseMessage。不要使用 ActionResult 或 IEnumerable!

      ActionResult 不好,因为正如您所发现的那样。

      返回 IEnumerable 不好,因为您可能希望稍后扩展它并添加一些标头等。

      使用 JsonResult 不好,因为您应该允许您的服务可扩展并支持其他响应格式,以防万一;如果你真的想限制它,你可以使用动作属性来做到这一点,而不是在动作正文中。

      public HttpResponseMessage GetAllNotificationSettings()
      {
          var result = new List<ListItems>();
          // Filling the list with data here...
      
          // Then I return the list
          return Request.CreateResponse(HttpStatusCode.OK, result);
      }
      

      在我的测试中,我通常使用下面的辅助方法从 HttpResponseMessage 中提取我的对象:

       public class ResponseResultExtractor
          {
              public T Extract<T>(HttpResponseMessage response)
              {
                  return response.Content.ReadAsAsync<T>().Result;
              }
          }
      
      var actual = ResponseResultExtractor.Extract<List<ListItems>>(response);
      

      通过这种方式,您实现了以下目标:

      • 您的操作还可以返回错误消息和状态代码,如 404 未找到,因此您可以通过上述方式轻松处理它。
      • 您的操作不仅限于 JSON,还支持 JSON,具体取决于客户端的请求首选项和 Formatter 中的设置。

      看这个:http://www.asp.net/web-api/overview/formats-and-model-binding/content-negotiation

      【讨论】:

      【解决方案4】:

      使用 WebAPI 时,您应该只返回 Object 而不是专门返回 Json,因为 API 将根据请求返回 JSON 或 XML。

      我不确定您的 WebAPI 为何返回 ActionResult,但我会将代码更改为类似;

      public IEnumerable<ListItems> GetAllNotificationSettings()
      {
          var result = new List<ListItems>();
          // Filling the list with data here...
      
          // Then I return the list
          return result;
      }
      

      如果您从某些 AJAX 代码调用它,这将产生 JSON。

      附言 WebAPI 应该是 RESTful 的,所以你的 Controller 应该叫做 ListItemController 而你的 Method 应该叫做 Get。但那是另一天。

      【讨论】:

      • +1 但是关于你的最后一点,REST 与控制器或方法的名称无关。
      • @demoncodemonkey 不是真的,但从问题中进行的命名约定,我可以猜到它们在同一个控制器中有许多 Get 的负载,它们返回不同的对象。 Cleaner (IMO) 保持 HttpGet 的命名为 Get
      • 同意,但与 REST 无关 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-30
      • 2012-08-29
      相关资源
      最近更新 更多