【发布时间】:2018-04-12 18:38:20
【问题描述】:
我正在尝试从 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给我 empty 404 响应
最后一种情况是我的问题。当我在委托处理程序的最后一行设置断点时,我清楚地看到errorResponse 包含具有正确值的ObjectContent<string>。但是为什么这个值稍后会被清除呢?
【问题讨论】:
-
那么您确定“/api/values/42/missing”会命中您的处理程序吗?我在我的环境中进行了测试(与您的环境不同,但仍然如此),对我来说,这个处理程序完全被绕过,响应由 IIS 提供。
-
可能是路由问题?我必须做一些阅读,但也许
DelegatingHandler正在执行,但下游事件由于未知路由而挤压响应?根据Asp.Net docs,HttpRoutingDispatcher似乎在自定义处理程序之后运行。 -
@Evk 是的,完全确定。处理程序得到
HttpError的响应,状态为"No route data was found for this request."。然后这个响应被新的errorResponse替换并返回到管道(我想它应该去HttpServer)。也许是自己的问题? -
@claylong 我也有同样的想法,但快速检查 asp.net 资源和web.api message lifecycle 海报让我确信调度员会追踪所有处理程序
标签: c# asp.net-web-api asp.net-web-api2 owin delegatinghandler