我可以创建一个只接受URL大写的ASP MVC路由吗?

时间:2012-10-22 09:56:02

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

我有以下路线:

context.MapRoute(
    "content",
    "{page}/{title}",
    new { controller = "Server", action = "Index" },
    new { page = @"^[AFL][0-9A-Z]{4}$" }
);

此路线用于以下页面:

/A1234
/F6789
/L0123

然而它也会抓住:/Admin这是我不想要的东西。

我提出了一个临时解决方案,如下所示:

context.MapRoute(
    "content",
    "{page}/{title}",
    new { controller = "Server", action = "Index" },
    new { page = @"^[AFL][0-9][0-9A-Z]{3}$" }
);

这只能起作用,因为现在我的所有页面的第二个数字都是0。

有没有办法可以配置我的路由接受A,F或L后跟4个大写字符,但不能捕获“dmin”?

不确定是否是这种情况,但我认为正则表达式不应该接受“dmin”,因为它是小写的,我只指定A-Z。但是当用作MVC路由时,它确实需要“dmin”。有没有人知道ASP MVC内部是否将其转换为全部大写?

2 个答案:

答案 0 :(得分:7)

解决方案1:自定义路径约束类

默认路由处理会在匹配URL时忽略大小写(请参阅下面的代码),这也是您案例中 Admin 匹配的原因。您应该做的就是编写一个自定义路由约束类,该类实现IRouteConstraint接口并适当地实现Match方法以区分大小写。

Here's a tutorial to get you started

解决方案2:自定义Route

如果你看一下默认Route类如何处理约束,这就是代码:

protected virtual bool ProcessConstraint(HttpContextBase httpContext, object constraint, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
    IRouteConstraint routeConstraint = constraint as IRouteConstraint;

    // checks custom constraint class instances
    if (routeConstraint != null)
    {
        return routeConstraint.Match(httpContext, this, parameterName, values, routeDirection);
    }

    // No? Ok constraint provided as regular expression string then?
    string text = constraint as string;
    if (text == null)
    {
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("Route_ValidationMustBeStringOrCustomConstraint"), new object[]
        {
            parameterName,
            this.Url
        }));
    }
    object value;
    values.TryGetValue(parameterName, out value);
    string input = Convert.ToString(value, CultureInfo.InvariantCulture);
    string pattern = "^(" + text + ")$";

    // LOOK AT THIS LINE
    return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant);
}

最后一行实际匹配提供的正则表达式路由约束。你可以看到它忽略了大小写。因此,第二种可能的解决方案是编写一个继承自此默认Route类的新Route类,并将ProcessConstraint方法覆盖为忽略大小写。其他一切都可以保持不变。

答案 1 :(得分:0)

另一种选择是像这样的正则表达式:

@"^(?!Admin)[AFL][0-9][0-9A-Z]{3}$"

在尝试使用正则表达式的其余部分之前,会将Admin排除在可能的匹配项之前。