MVC动作无效参数给出参数异常500而不是404

本文关键字:参数 异常 无效 MVC | 更新日期: 2023-09-27 17:53:38

当我有一个这样的控制器动作

public ActionResult _Files(long parentid)
        {

,如果你在没有parentid的浏览器中调用该操作。它抛出一个系统。ArgumentException和500个响应

parameters字典包含一个空的parameter条目非空类型的parentid。Int64' for方法"System.Web.Mvc.ActionResult带有_file

该操作不应该在没有PARENTID的情况下调用。是否有一种方法可以不抛出异常(并返回500个响应),而是返回400个错误请求或404未找到(这两种方法都更有意义)。

MVC动作无效参数给出参数异常500而不是404

正在寻找一种解决方案,可以在整个web应用程序中以通用的方式做到这一点?

我建议你看一下路由约束。创建路由约束需要传递一个整数作为parentid,如果没有提供,路由将不匹配,默认情况下将返回404。

下面是一个例子:

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

有关路由约束的更多信息,请参阅本文。

这种方法的唯一缺点是regex不检查输入值是long还是更大的值。但是,如果这是一个问题,您可以轻松地创建一个自定义路由约束来检查输入值是否可以被解析为long

参考资料: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));
}

你可以做的是:

    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.