【问题标题】:Return empty json on null in WebAPI在 WebAPI 中返回空 json
【发布时间】:2014-05-10 20:36:03
【问题描述】:

webApi 返回 null 对象时,是否可以返回 { } 而不是 null? 这是为了防止我的用户在解析响应时出错。并使响应成为有效的 Json 响应?

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

【问题讨论】:

  • 如果你没有什么要返回,响应不应该为空,而是 404(未找到)。
  • 如果您使用 WebApi 来构建 RESTful api,那么我同意@Mark Seemann。如果您只是使用 webApi 进行 url 路由并且并不真正打算遵循 REST 实践,那么您可以返回任何您想要的。
  • 确实我的项目正在尝试遵循 REST 实践,所以我同意 @MarkSeemann。请把你的评论作为答案,我会接受的。
  • @spons Done :)
  • 只发送新对象 {} 而不是 null .. 尝试关注但他们返回“{}” .. 我试过这个 -- 新对象 {}

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


【解决方案1】:

如果您正在构建 RESTful 服务,并且没有任何可从资源返回的内容,我相信返回 404 (Not Found) 比返回带有空主体的 200 (OK) 响应更正确。

【讨论】:

  • 这不会让人困惑吗?如中,如果服务器也关闭,您将收到 404。怎么区分?
  • @andrewjboyd 是的,对于一个列表,我会返回一个空列表,但这在概念上也是一种不同的资源。列表始终存在,但有时可能为空。另一方面,“单一”资源要么存在,要么不存在。
  • 回答错误,需要返回204。看我的回答stackoverflow.com/a/32804589/631527
  • 除非您 100.000% 确定,否则不要只说“错误答案”。对于试图找到解决方案的人来说,这真的很令人困惑。答案是正确的 RESTfull 服务。此外,除了少数情况外,您提出的解决方案在所有情况下都有点错误(尽管示例不适合评论)
  • 重读这个讨论,我意识到我已经隐含地将这个问题解释为与 GET 请求有关。有了这种解释,我相信我的回答是正确的。不过,OP 并没有具体说明这一点,所以我的解释可能不正确。例如,如果我们正在讨论 POST 请求,如果操作成功,我会认为 404 显然是不正确的。
【解决方案2】:

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

  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());

【讨论】:

  • 一段很棒的代码;我仍然会在接受的答案中遵循 Mark Seemann 的建议,而不是返回空的 JSON 对象,而是返回 HTTP 404 Not Found 消息。
  • @DavidKeaveny 有时 204 比 404 更合适。想象一下 URL /AccidentsToday/FailedTests
  • 那些 URI 意味着返回一个集合,在这种情况下,我倾向于总是返回一个带有 HTTP 200 的空数组。至于 HTTP 204,我返回 204 表示成功的 PUT 和 DELETE 操作;所以在我的 NullJsonHandler 中,我检查请求方法以确保它是 GET。
  • @DavidKeaveny,我收到“发送 HTTP 标头后服务器无法附加标头”。尝试“ContinueWith”无济于事,您能否提供一些启示。
  • @Samuel 您使用的是什么版本的 Web API?另一种方法是创建自定义的 JsonFormatter。从标准方法派生并覆盖标准方法之一。
【解决方案3】:

感谢 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 中的 Ok()

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
        };
    }
}

在 ApiController 中重写 Ok()

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

【讨论】:

    【解决方案4】:

    也许更好的解决方案是使用自定义消息处理程序。

    委托处理程序也可以跳过内部处理程序并直接 创建响应。

    自定义消息处理程序:

    public class NullJsonHandler : DelegatingHandler
        {
            protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
    
                var updatedResponse = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = null
                };
    
                var response = await base.SendAsync(request, cancellationToken);
    
                if (response.Content == null)
                {
                    response.Content = new StringContent("{}");
                }
    
                else if (response.Content is ObjectContent)
                {
    
                    var contents = await response.Content.ReadAsStringAsync();
    
                    if (contents.Contains("null"))
                    {
                        contents = contents.Replace("null", "{}");
                    }
    
                    updatedResponse.Content = new StringContent(contents,Encoding.UTF8,"application/json");
    
                }
    
                var tsc = new TaskCompletionSource<HttpResponseMessage>();
                tsc.SetResult(updatedResponse);   
                return await tsc.Task;
            }
        }
    

    注册处理程序:

    Application_Start() 方法内的Global.asax 文件中,通过添加以下代码来注册您的处理程序。

    GlobalConfiguration.Configuration.MessageHandlers.Add(new NullJsonHandler());
    

    现在所有包含nullAsp.NET Web API 响应将被替换为空Json 正文{}

    参考资料:
    - https://stackoverflow.com/a/22764608/2218697
    - https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/http-message-handlers

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 2019-05-18
      • 2012-05-07
      • 2015-02-24
      • 2017-06-12
      • 2016-05-20
      • 2016-02-12
      相关资源
      最近更新 更多