这篇博文将引导您处理 ASP.Net Web API 中的 404 错误:http://weblogs.asp.net/imranbaloch/handling-http-404-error-in-asp-net-web-api http://weblogs.asp.net/imranbaloch/handling-http-404-error-in-asp-net-web-api
假设您正在使用 ASP.NET Web API 框架开发 HTTP RESTful 应用程序。在此应用程序中,您需要在集中位置处理 HTTP 404 错误。从 ASP.NET Web API 的角度来看,您需要处理这些情况,
- 没有匹配的路线。
- 路由已匹配,但在路由上未找到 {controller}。
- 未找到名称为 {controller} 的类型。
- 由于没有以请求 HTTP 方法动词开头的操作方法,或者没有找到具有 IActionHttpMethodProviderRoute 实现属性的操作方法,或者没有找到具有 {action} 名称的方法,或者没有找到具有匹配的 {action} 名称的方法,因此在所选控制器中找不到匹配的操作方法。
现在,让我们使用 Handle404 操作方法创建一个 ErrorController。此操作方法将在上述所有情况下用于向客户端发送 HTTP 404 响应消息。
public class ErrorController : ApiController
{
[HttpGet, HttpPost, HttpPut, HttpDelete, HttpHead, HttpOptions, AcceptVerbs("PATCH")]
public HttpResponseMessage Handle404()
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.NotFound);
responseMessage.ReasonPhrase = "The requested resource is not found";
return responseMessage;
}
}
您可以轻松更改上述操作方法以发送一些其他特定的 HTTP 404 错误响应。如果 HTTP 服务的客户端向资源(uri)发送请求,并且服务器上没有与此 uri 匹配的路由,那么您可以使用自定义路由将请求路由到上述 Handle404 方法。将此路由放在路由配置的最底部,
routes.MapHttpRoute(
name: "Error404",
routeTemplate: "{*url}",
defaults: new { controller = "Error", action = "Handle404" }
);
现在,您需要处理匹配路由中没有 {controller} 或找不到具有 {controller} 名称的类型时的情况。您可以轻松处理这种情况,并使用自定义 IHttpControllerSelector 将请求路由到上述 Handle404 方法。这是自定义 IHttpControllerSelector 的定义,
public class HttpNotFoundAwareDefaultHttpControllerSelector : DefaultHttpControllerSelector
{
public HttpNotFoundAwareDefaultHttpControllerSelector(HttpConfiguration configuration)
: base(configuration)
{
}
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
HttpControllerDescriptor decriptor = null;
try
{
decriptor = base.SelectController(request);
}
catch (HttpResponseException ex)
{
var code = ex.Response.StatusCode;
if (code != HttpStatusCode.NotFound) throw;
var routeValues = request.GetRouteData().Values;
routeValues["controller"] = "Error";
routeValues["action"] = "Handle404";
decriptor = base.SelectController(request);
}
return decriptor;
}
}
接下来,如果由于上述原因在所选控制器中没有找到匹配的action方法,还需要将请求传递给上述Handle404方法。这种情况也可以通过自定义 IHttpActionSelector 轻松处理。这里是自定义IHttpActionSelector的源码,
public class HttpNotFoundAwareControllerActionSelector : ApiControllerActionSelector
{
public HttpNotFoundAwareControllerActionSelector()
{
}
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
HttpActionDescriptor decriptor = null;
try
{
decriptor = base.SelectAction(controllerContext);
}
catch (HttpResponseException ex)
{
var code = ex.Response.StatusCode;
if (code != HttpStatusCode.NotFound && code != HttpStatusCode.MethodNotAllowed) throw;
var routeData = controllerContext.RouteData;
routeData.Values["action"] = "Handle404";
IHttpController httpController = new ErrorController();
controllerContext.Controller = httpController;
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "Error", httpController.GetType());
decriptor = base.SelectAction(controllerContext);
}
return decriptor;
}
}
最后,我们需要注册自定义的IHttpControllerSelector和IHttpActionSelector。打开 global.asax.cs 文件并添加这些行,
configuration.Services.Replace(typeof(IHttpControllerSelector), new HttpNotFoundAwareDefaultHttpControllerSelector(configuration));
configuration.Services.Replace(typeof(IHttpActionSelector), new HttpNotFoundAwareControllerActionSelector());