Ответ 1
Если вы создаете службу RESTful и не можете ничего не возвращать из ресурса, я считаю, что было бы вернее возвращать 404 (не найдено), чем 200 (OK) с пустым телом.
Можно ли возвращать {} вместо null, когда webApi возвращает нулевой объект? Это, чтобы мой пользователь не получал ошибок при анализе ответа. И чтобы сделать ответ действительным Json Response?
Я знаю, что я могу настроить его везде вручную. То, что когда 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());
Спасибо Даррел Миллер, я сейчас использую это решение.
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, чтобы использовать Ok() в 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
};
}
}
Переопределить Ok() в ApiController
public class BaseApiController : ApiController
{
protected override OkResult Ok()
{
return new OkJsonPatchResult(this);
}
}