在Web API中返回null上的空json

时间:2014-03-31 13:22:50

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

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

我知道我可以手动设置它。当null是响应时,应该返回一个空的Json对象。但是,有没有办法自动为每个响应做到这一点?

4 个答案:

答案 0 :(得分:15)

如果您正在构建RESTful服务,并且无法从资源中返回任何内容,我认为返回404 (Not Found)而不是200 (OK)响应更为正确体。

答案 1 :(得分:8)

您可以使用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());

答案 2 :(得分: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中的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);
    }
}

答案 3 :(得分:0)

更好的解决方案

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

  

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

自定义消息处理程序:

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

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

<强>参考文献:

1.

2.