Return empty json on null in WebAPI

后端 未结 4 992
野性不改
野性不改 2021-02-04 02:50

Is it possible to return { } instead of null when webApi returns a null object? This, to prevent my user from getting errors while parsing the response. And to make the respon

相关标签:
4条回答
  • 2021-02-04 03:29

    Thanks to Darrel Miller, I for now use this solution.


    WebApi messes with StringContent "{}" again in some environment, so serialize through 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;
        }
    }
    

    Derived from OkResult to take advantage Ok() in 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
            };
        }
    }
    

    Override Ok() in ApiController

    public class BaseApiController : ApiController
    {
        protected override OkResult Ok()
        {
            return new OkJsonPatchResult(this);
        }
    }
    
    0 讨论(0)
  • 2021-02-04 03:32

    If you are building a RESTful service, and have nothing to return from the resource, I believe that it would be more correct to return 404 (Not Found) than a 200 (OK) response with an empty body.

    0 讨论(0)
  • 2021-02-04 03:36

    You can use a HttpMessageHandler to perform behaviour on all requests. The example below is one way to do it. Be warned though, I whipped this up very quickly and it probably has a bunch of edge case bugs, but it should give you the idea of how it can be done.

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

    You can enable this handler by doing,

    config.MessageHandlers.Add(new NullJsonHandler());
    
    0 讨论(0)
  • 2021-02-04 03:50

    Maybe better solution is using Custom Message Handler.

    A delegating handler can also skip the inner handler and directly create the response.

    Custom Message Handler:

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

    Register the Handler:

    In Global.asax file inside Application_Start() method register your Handler by adding below code.

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

    Now all the Asp.NET Web API Response which contains null will be replaced with empty Json body {}.

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

    0 讨论(0)
提交回复
热议问题