如何处理MVC3路由的空参数字典错误?

时间:2012-03-14 21:34:29

标签: asp.net-mvc routes

我使用的大多数路由都基于标准MVC3应用程序中定义的默认路由:

 routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional });

但是,如果我的路由是“/ Book / Update / 1”并且由于用户在没有1的情况下手动键入地址而保持“1”,则抛出空参数错误。显然我的路线需要这个1并且不是可选的,但我不会为我的每一个动作定义一个自定义路线。如果我打开自定义错误,我不确定这是什么类型的错误,重定向到正确的HTML错误页面。

问题: 我如何处理这个错误,就像404一样?我没有看到这种方法有任何问题,因为现实是在路线中留下一个Id号码与找不到的404号码相同。

或者我在设计路线时遗漏了什么?似乎很直接给我。

感谢。

更新 我很欣赏下面给出的答案。它们都是合理的方法。为了更清楚我的问题,让我详细说明一下。在我看来,“/ Book / Update / 1”的路线只有一个目的。更新书1.除此之外的任何其他偏差都应该失败并重定向到404.我不认为这与不存在的静态html页面有任何不同。我可能会争论一个不包含在.net中的功能,我只是觉得可能有更简单的方法。

UPDATE2: 应该挖得更深一些。有一个很好的例子here.我发现第二个答案最有帮助。

3 个答案:

答案 0 :(得分:2)

public ActionResult Update(int? id)
{
    if (!id.HasValue) return HttpNotFound();

    //Debug.Assert(id.Value != null);
    ...
}

答案 1 :(得分:0)

我也有这个问题,我所做的是创建一个可重复使用的动作过滤器,我在其中指定所需的参数。

动作过滤器:

  public class RequiredActionParameters : ActionFilterAttribute
{
    private readonly IEnumerable<string> _parameters;

    public RequiredActionParameters(params string[] parameters)
    {
        _parameters = parameters;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!filterContext.IsChildAction && !filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            foreach (var parameter in _parameters)
            {
                if (filterContext.ActionParameters[parameter] == null)
                {
                    filterContext.Result = new RedirectResult("/Error/NotFound");
                    break;
                }
            }
        }
    }
}

关于控制器中的操作:

 [RequiredActionParameters("restaurantId", "testId")]
 public ActionResult Details(long restaurantId, long testId)
 {
        View();
 }

我使用错误日志工具elmah对其进行了测试,并且没有报告任何错误。

答案 2 :(得分:0)

我认识的那个聚会晚了,但希望这可能对其他人有帮助。我在上面回答了杰米(Jamie)的问题,并对其进行了扩展,使其更易于使用,因此您无需单独列出所有参数,无需从不同操作中进行不同的重定向,并自动考虑可为空的类型参数。

public class RequiredActionParametersAttribute : ActionFilterAttribute
{
    private readonly string _redirectUrlConfigKey;

    public RequiredActionParametersAttribute(string redirectUrlConfigKey)
    {
        _redirectUrlConfigKey = redirectUrlConfigKey;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (string.IsNullOrWhiteSpace(_redirectUrlConfigKey))
            return;

        var redirectUrl = ConfigurationManager.AppSettings[_redirectUrlConfigKey];
        if (string.IsNullOrWhiteSpace(redirectUrl))
            return;

        var actionDescriptor = filterContext.ActionDescriptor;
        var parameterDescriptors = actionDescriptor.GetParameters();

        foreach (var parameter in filterContext.ActionParameters)
        {
            if (parameter.Value == null)
            {
                var parameterDescriptor = parameterDescriptors.First(p => p.ParameterName == parameter.Key);
                if (!IsNullableType(parameterDescriptor.ParameterType))
                {
                    filterContext.Result = new RedirectResult(redirectUrl);
                    break;
                }
            }
        }
    }

    private static bool IsNullableType(Type type)
    {
        return Nullable.GetUnderlyingType(type) != null;
    }
}

然后采取行动

    [RequiredActionParameters("DetailsPageExceptionRedirect")]
    public ActionResult Details(int param1, int param2, bool param3, int? param4)

您可以将针对不同操作的不同重定向添加到配置文件,并将config键传递到操作过滤器。然后它将检查每个参数的存在,如果它为null,则检查它是否为可为null的类型,否则,将重定向到您指定的位置。