在 WebAPI 中的 null 上返回空 json

本文关键字:返回 json null WebAPI 中的 | 更新日期: 2023-09-27 17:55:35

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

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

在 WebAPI 中的 null 上返回空 json

如果您正在构建一个 RESTful 服务,并且没有从资源返回的内容,我相信返回 404(未找到)比返回带有空正文的 200(OK)响应更正确。

您可以使用

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

感谢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 以利用 API 控制器中的 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
        };
    }
}

在 API 控制器中覆盖 Ok()

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

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

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

自定义消息处理程序:

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

注册处理程序:

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

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

现在,包含null的所有Asp.NET Web API响应都将替换为空Json正文{}

引用:
- https://stackoverflow.com/a/22764608/2218697
- https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/http-message-handlers