忽略由于缺少控制器参数而导致的异常

时间:2013-10-15 10:40:25

标签: c# .net asp.net-mvc asp.net-mvc-4

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

例如:

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响应,并在代码中的单个位置指定此响应以应用于所有控制器。< / p>

如何做到这一点?

2 个答案:

答案 0 :(得分:1)

似乎有效的一种方法是覆盖控制器中的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。

答案 1 :(得分:0)

您可以使用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);
}

MissingArgument视图应位于“共享”视图文件夹中。 如果要将特定的HTTP错误代码发送回客户端,可以将其放在视图中:

@{
    ViewBag.Title = "Error";
    Context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
 }

<h2>Not found</h2>