2014-03-31 93 views
10

当webApi返回空对象时,是否可以返回{}而不是null? 这样可以防止我的用户在解析响应时收到错误。并使响应成为有效的Json响应?在WebAPI中返回空json null

我知道我可以在任何地方手动设置它。当null是响应时,应该返回一个空的Json对象。但是,有没有办法为每个响应自动执行?

+2

如果你什么都没有返回,响应不应该null,但404(未找到)。 –

+2

如果您使用WebApi来构建RESTful API,那么我同意@Mark Seemann。如果您只是使用webApi进行网址路由,并且不打算遵循REST实践,那么您可以返回任何您想要的内容。 – bsayegh

+1

的确,我的项目正在尝试遵循REST实践,所以我同意@MarkSeemann。请把你的评论作为答案,我会接受它。 – spons

回答

12

如果你正在建设一个RESTful服务,并没有什么可从资源恢复,我相信,这将是更正确的返回404 (Not Found)而不是空的正文响应200 (OK)

+1

难道不会让人感到困惑吗?如在,如果服务器也关闭,你将得到一个404。你怎么能区分这个区别? – andrewjboyd

+0

重要吗?作为客户端,您需要知道的是该URL没有资源。原因是一个实现细节。 –

+0

我是第一个承认我不是专家,但是你不想告诉用户,如果你不能与服务器通信,你不能通信吗? 404对于获取单个对象是很好的,但是如果你要返回一个对象列表,不会更正确吗? – andrewjboyd

7

您可以使用HttpMessageHandler对所有请求执行行为。下面的例子是一种方法。不过要注意的是,我很快就把它搞砸了,它可能有一堆边缘案例的bug,但它应该让你知道如何做到这一点。

public class NullJsonHandler : DelegatingHandler 
    { 
     protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
     { 

      var response = await base.SendAsync(request, cancellationToken); 
      if (response.Content == null) 
      { 
       response.Content = new StringContent("{}"); 
      } else if (response.Content is ObjectContent) 
      { 
       var objectContent = (ObjectContent) response.Content; 
       if (objectContent.Value == null) 
       { 
        response.Content = new StringContent("{}"); 
       } 

      } 
      return response; 
     } 
    } 

您可以启用此处理程序做,

config.MessageHandlers.Add(new NullJsonHandler()); 
+0

一段伟大的代码;我仍然会在接受的答案中遵循Mark Seemann的建议,而不是返回空的JSON对象,而是返回一个HTTP 404 Not Found消息。 –

+0

@DavidKeaveny有时候204会比404更合适。想象一下URL'/ AccidentsToday'或'/ FailedTests' –

+0

这些URI意味着集合的返回,在这种情况下,我会倾向于总是返回一个空的数组与HTTP 200.至于HTTP 204,我返回204s成功的PUT和DELETE操作;所以在我的NullJsonHandler中,我检查了请求方法以确保它是一个GET。 –

0

感谢Darrel Miller,我现在使用这个解决方案。


的WebAPI食堂用的StringContent “{}” 又在一些环境中,所以通过HttpContent序列。

/// <summary> 
/// Sends HTTP content as JSON 
/// </summary> 
/// <remarks>Thanks to Darrel Miller</remarks> 
/// <seealso cref="http://www.bizcoder.com/returning-raw-json-content-from-asp-net-web-api"/> 
public class JsonContent : HttpContent 
{ 
    private readonly JToken jToken; 

    public JsonContent(String json) { jToken = JObject.Parse(json); } 

    public JsonContent(JToken value) 
    { 
     jToken = value; 
     Headers.ContentType = new MediaTypeHeaderValue("application/json"); 
    } 

    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) 
    { 
     var jw = new JsonTextWriter(new StreamWriter(stream)) 
     { 
      Formatting = Formatting.Indented 
     }; 
     jToken.WriteTo(jw); 
     jw.Flush(); 
     return Task.FromResult<object>(null); 
    } 

    protected override bool TryComputeLength(out long length) 
    { 
     length = -1; 
     return false; 
    } 
} 

从OkResult导出ApiController利用好()在ApiController

public class OkJsonPatchResult : OkResult 
{ 
    readonly MediaTypeWithQualityHeaderValue acceptJson = new MediaTypeWithQualityHeaderValue("application/json"); 

    public OkJsonPatchResult(HttpRequestMessage request) : base(request) { } 
    public OkJsonPatchResult(ApiController controller) : base(controller) { } 

    public override Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) 
    { 
     var accept = Request.Headers.Accept; 
     var jsonFormat = accept.Any(h => h.Equals(acceptJson)); 

     if (jsonFormat) 
     { 
      return Task.FromResult(ExecuteResult()); 
     } 
     else 
     { 
      return base.ExecuteAsync(cancellationToken); 
     } 
    } 

    public HttpResponseMessage ExecuteResult() 
    { 
     return new HttpResponseMessage(HttpStatusCode.OK) 
     { 
      Content = new JsonContent("{}"), 
      RequestMessage = Request 
     }; 
    } 
} 

覆盖好()

public class BaseApiController : ApiController 
{ 
    protected override OkResult Ok() 
    { 
     return new OkJsonPatchResult(this); 
    } 
}