我试图从web.api返回自定义错误响应。让它是简单的字符串"Oops!"格式为json。因此,我创建了简单的委托处理程序,它替换了如下所示的错误响应:
public class ErrorMessageHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (response.IsSuccessStatusCode)
return response;
var formatter = new JsonMediaTypeFormatter();
var errorResponse = request.CreateResponse(response.StatusCode, "Oops!", formatter);
return errorResponse;
}
}接下来,我确保这是管道中唯一的一个消息处理程序:
httpConfig.MessageHandlers.Clear();
httpConfig.MessageHandlers.Add(new ErrorMessageHandler());
// Only default route
httpConfig.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(httpConfig); // OWIN self-hosting控制器也是最简单的:
public class ValuesController : ApiController
{
public IHttpActionResult Get(int id)
{
if (id == 42)
return Ok("Answer to the Ultimate Question of Life, the Universe, and Everything");
return NotFound();
}
}有趣的是:
/api/values/42给我200个值字符串的响应/api/values/13使用自定义的"Oops!"字符串提供404响应。/api/values/42/missing给我空的404响应最后一个案子是我的问题。当我在委托处理程序的最后一行上设置一个断点时,我清楚地看到errorResponse包含具有正确值的ObjectContent<string>。但是为什么这个值稍后会被清除掉呢?
发布于 2017-10-31 16:45:07
原因是HttpMessageHandlerAdapter.InvokeCore中的代码(基本上是在UseWebApi中间件中):
response = await _messageInvoker.SendAsync(request, cancellationToken);
// ...
if (IsSoftNotFound(request, response)) {
callNext = true;
}
else {
// ...
}其中IsSoftNotFound是:
private static bool IsSoftNotFound(HttpRequestMessage request, HttpResponseMessage response)
{
if (response.StatusCode == HttpStatusCode.NotFound)
{
bool routingFailure;
if (request.Properties.TryGetValue<bool>(HttpPropertyKeys.NoRouteMatched, out routingFailure)
&& routingFailure)
{
return true;
}
}
return false;
}因此,基本上在"soft“404的情况下,"soft”意味着没有匹配的路由(并由request.Properties中具有特定密钥的属性指示)--中间件将调用下一个组件。否则-只会发出回应。
对于您的情况,这个IsSoftDelete是正确的(因为确实没有匹配的路由),而下一个组件(没有时间弄清楚这是什么)会清除您的响应内容。
若要“修复”此问题,请在以前的处理程序处理完请求后,使用该键从请求中删除属性:
public class ErrorMessageHandler : DelegatingHandler {
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken) {
var response = await base.SendAsync(request, cancellationToken);
if (response.IsSuccessStatusCode)
return response;
// here, can also check if 404
request.Properties.Remove(HttpPropertyKeys.NoRouteMatched);
var formatter = new JsonMediaTypeFormatter();
var errorResponse = request.CreateResponse(response.StatusCode, "Oops!", formatter);
return errorResponse;
}
}https://stackoverflow.com/questions/47038018
复制相似问题