忽略因缺少控制器参数而导致的异常
本文关键字:异常 参数 控制器 | 更新日期: 2023-09-27 18:35:29
我有一个使用 MVC4 构建的面向互联网的网站,我偶尔会收到来自机器人或好奇用户的错误报告,他们发送不完整的 URL 请求。
例如:
public class ProductController : Controller
{
[HttpGet]
public void View(int id)
{
// ...
- 对
/product/view/1
的 GET 请求有效。 - 对
/product/view
的 GET 请求无效,因为未指定参数。
此类无效请求会引发类似于以下内容的异常:
System.ArgumentException: The parameters dictionary contains a null entry
for parameter 'id' of non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult View(Int32)' in 'Foo.ProductController'. An
optional parameter must be a reference type, a nullable type, or be declared
as an optional parameter.
Parameter name: parameters
at System.Web.Mvc.ActionDescriptor.ExtractParameterFromDictionary(ParameterInfo parameterInfo, IDictionary`2 parameters, MethodInfo methodInfo)
at System.Web.Mvc.ReflectedActionDescriptor.<>c__DisplayClass1.<Execute>b__0(ParameterInfo parameterInfo)
...
如异常消息所述,我可以使id
参数为空并在操作方法中进行检查,但我有许多控制器具有许多操作。
我想向任何无法将参数绑定到操作参数的请求返回 BadRequest
/NotFound
响应,并在代码中的单个位置指定它以应用于所有控制器。
如何做到这一点?
一种似乎有效的方法是覆盖控制器中的OnActionExecuted
(我使用基本控制器,所以会把它放在那里。
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception == null)
return;
// Avoid 'action parameter missing' exceptions by simply returning an error response
if (filterContext.Exception.TargetSite.DeclaringType == typeof(ActionDescriptor) &&
filterContext.Exception.TargetSite.Name == "ExtractParameterFromDictionary")
{
filterContext.ExceptionHandled = true;
filterContext.Result = new HttpStatusCodeResult((int)HttpStatusCode.BadRequest);
}
}
这样做感觉有点不舒服,因为它可能会在框架的未来版本中中断。但是,如果它确实中断了,那么该网站将恢复为返回 500 而不是 400。
可以使用 HandleError 属性来处理应用程序中的错误。可以在控制器级别和方法级别指定 HandleError 属性。我以前用过这样的东西:
[HandleError(ExceptionType = typeof(ArgumentException), View = "MissingArgument")]
public ActionResult Test(int id)
{
return View();
}
如果不想在每个方法的基础上捕获异常,则可以将属性放在类级别:
[HandleError(ExceptionType = typeof(ArgumentException), View = "MissingArgument")]
public class HomeController : Controller
{
}
如果要在一个中心位置处理此问题,可以将其添加到 App-Start 文件夹中的 FilterConfig 类中:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
var error = new HandleErrorAttribute();
error.ExceptionType = typeof (ArgumentException);
error.View = "MissingArgument";
filters.Add(error);
}
"缺少参数"视图应位于"共享视图"文件夹中。如果要将特定的 HTTP 错误代码发送回客户端,可以将其放在视图中:
@{
ViewBag.Title = "Error";
Context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
}
<h2>Not found</h2>