簡體   English   中英

在 WebAPI 中返回 null 上的空 json

[英]Return empty json on null in WebAPI

當 webApi 返回 null 對象時,是否可以返回 { } 而不是 null? 這是為了防止我的用戶在解析響應時出錯。 並使響應成為有效的 Json 響應?

我知道我可以在任何地方手動設置它。 當 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 以利用 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);
    }
}

也許更好的解決方案是使用自定義消息處理程序。

委托處理程序也可以跳過內部處理程序並直接創建響應。

自定義消息處理程序:

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 body {}

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM