忽略控制器参数缺失导致的异常

Dre*_*kes 6 .net c# asp.net-mvc asp.net-mvc-4

我有一个使用 MVC4 构建的面向互联网的网站,我偶尔会收到来自机器人或好奇的用户发送不完整 URL 请求的错误报告。

例如:

public class ProductController : Controller
{
    [HttpGet]
    public void View(int id)
    {
        // ...
Run Code Online (Sandbox Code Playgroud)
  • GET 请求/product/view/1有效。
  • /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)
   ...
Run Code Online (Sandbox Code Playgroud)

正如异常消息所述,我可以使id参数可为空并在操作方法中进行检查,但我有许多具有许多操作的控制器。

我想对任何无法将参数绑定到操作参数的请求返回BadRequest/NotFound响应,并在代码中的一个位置指定它以应用于所有控制器。

如何才能做到这一点?

Dre*_*kes 4

一种似乎有效的方法是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样做感觉有点不舒服,因为它可能会在框架的未来版本中崩溃。但是,如果它确实损坏,则该网站将恢复返回 500 个而不是 400 个。

  • 您还可以重写 OnException 方法以获得相同的效果。不知道这是否重要,但我猜想每个调用的操作方法都会调用 OnActionExecuted,而 OnException 仅在发生异常时才被调用。只是一个想法。 (2认同)