mvc动作无效参数给出了argumentexception 500而不是404

时间:2014-03-26 20:49:27

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

当我有这样的控制器动作时。

public ActionResult _Files(long parentid)
        {

如果您从没有parentid的浏览器调用该操作。它抛出一个System.ArgumentException和一个500响应

  

参数字典包含参数的空条目   ' parentId的'非可空类型的System.Int64'方法   ' System.Web.Mvc.ActionResult _Files

如果没有PARENTID设计,不应该调用该动作。有没有办法不抛出异常(并返回500响应),而是返回400错误请求或未找到404(其中任何一个会更有意义IMO)。寻找一种能够在Web应用程序中以通用方式执行此操作的解决方案吗?

3 个答案:

答案 0 :(得分:4)

我建议你看一下路线限制。创建路由约束将需要将整数作为parentid传递,如果未提供,则路由将不匹配,并且默认情况下将返回404。

以下是一个例子:

routes.MapRoute(
    name: "MyController",
    url: "MyController/{parentid}",
    defaults: new { controller = "MyController", action = "Index" },
    constraints: new { parentid = @"\d+" }
);

有关route constraints的更多信息,请参阅此文章。

此方法的唯一缺点是正则表达式不会检查输入值是long还是更大。但是,如果这是一个问题,您可以轻松创建自定义路由约束,以检查输入值是否可以解析为long

答案 1 :(得分:3)

参考:http://prideparrot.com/blog/archive/2012/5/exception_handling_in_asp_net_mvc

创建错误控制器类和相应的视图:

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    public ActionResult NotFound()
    {
        return View();
    }
}
Global.asax.cs中的

protected void Application_Error(object sender, EventArgs e)
{
    var httpContext = ((MvcApplication)sender).Context;
    var currentController = " ";
    var currentAction = " ";
    var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
    if (currentRouteData != null)
    {
        if (currentRouteData.Values["controller"] != null && 
            !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
        {
            currentController = currentRouteData.Values["controller"].ToString();
        }
        if (currentRouteData.Values["action"] != null && 
            !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
        {
            currentAction = currentRouteData.Values["action"].ToString();
        }
    }
    var ex = Server.GetLastError();
    var controller = new ErrorController();
    var routeData = new RouteData();
    var action = "Index";
    var statusCode = 500;
    if (ex is ArgumentException)
    {
        action = "NotFound";
        statusCode = 404;
    }
    httpContext.ClearError();
    httpContext.Response.Clear();
    httpContext.Response.StatusCode = statusCode;             
    httpContext.Response.TrySkipIisCustomErrors = true;
    routeData.Values["controller"] = "Error";
    routeData.Values["action"] = action;
    controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction);
    ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}

答案 2 :(得分:2)

你可以做的是:

    public ActionResult _Files(long  ? parentid)
    {

parentId可以为空。

然后在您的操作中,您需要按如下方式处理它:

    public ActionResult _Files(long  ? parentid)
    {
      if(parentId.HasValue == false) {return some http status code;}
      // Then you can use parentId with its Value property.