Den*_*gan 23 asp.net-mvc asp.net-mvc-2
我正在尝试编写一个带有可空int的路由.应该可以去这两个/profile/也是/profile/\d+.
routes.MapRoute("ProfileDetails", "profile/{userId}",
new {controller = "Profile",
action = "Details",
userId = UrlParameter.Optional},
new {userId = @"\d+"});
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我说这userId是可选的,但它应该与正则表达式匹配\d+.这不起作用,我明白为什么.
但是,我如何构建一个匹配的路由,/profile/但/profile/后面跟一个数字?
Mar*_*ell 28
在最简单的方法是只需添加另一条路线没有userId参数,让你有一个备用的:
routes.MapRoute("ProfileDetails", "profile/{userId}",
new {controller = "Profile",
action = "Details",
userId = UrlParameter.Optional},
new {userId = @"\d+"});
routes.MapRoute("Profile", "profile",
new {controller = "Profile",
action = "Details"});
Run Code Online (Sandbox Code Playgroud)
据我所知,唯一可以做到这一点的方法是使用自定义约束.所以你的路线会变成:
routes.MapRoute("ProfileDetails", "profile/{userId}",
new {controller = "Profile",
action = "Details",
userId = UrlParameter.Optional},
new {userId = new NullableConstraint());
Run Code Online (Sandbox Code Playgroud)
自定义约束代码如下所示:
using System;
using System.Web;
using System.Web.Routing;
using System.Web.Mvc;
namespace YourNamespace
{
public class NullableConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.IncomingRequest && parameterName == "userId")
{
// If the userId param is empty (weird way of checking, I know)
if (values["userId"] == UrlParameter.Optional)
return true;
// If the userId param is an int
int id;
if (Int32.TryParse(values["userId"].ToString(), out id))
return true;
}
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道这NullableConstraint是最好的名字,但这取决于你!
Che*_*hev 13
自从这个问题得到解答后,可能会发生一些变化,但我能够改变这个:
routes.MapPageRoute(
null,
"projects/{operation}/{id}",
"~/Projects/ProjectWizard.aspx",
true,
new RouteValueDictionary(new
{
operation = "new",
id = UrlParameter.Optional
}),
new RouteValueDictionary(new
{
id = new NullableExpressionConstraint(@"\d+")
})
);
Run Code Online (Sandbox Code Playgroud)
有了这个:
routes.MapPageRoute(
null,
"projects/{operation}/{id}",
"~/Projects/ProjectWizard.aspx",
true,
new RouteValueDictionary(new
{
operation = "new",
id = UrlParameter.Optional
}),
new RouteValueDictionary(new
{
id = @"\d*"
})
);
Run Code Online (Sandbox Code Playgroud)
简单地使用*而不是+在正则表达式中完成相同的任务.如果未包含参数,则仍会触发路径,但如果包含该参数,则只有在值为有效整数时才会触发.否则会失败.
ASP.NET MVC 3已经解决了这个问题,正如Alex Ford所说,你可以使用\d*而不是编写自定义约束.如果您的模式更复杂,比如寻找一年\d{4},只需确保您的模式符合您的要求以及空字符串,例如(\d{4})?或\d{4}|^$.无论什么让你开心.
如果您仍在使用ASP.NET MVC 2并希望使用Mark Bell的示例或NYCChris的示例,请注意只要URL参数包含与您的模式匹配的路由,路由就会匹配.这意味着该模式\d+将匹配参数abc123def.要避免这种情况,请在定义路径时或在自定义约束中使用^(和包装模式)$.(如果你看一下System.Web.Routing.Route.ProcessConstraint的反射,你会看到它这样做对您在使用内置的约束,同时也设置了CultureInvariant,编译和IGNORECASE选项.)
由于我已经使用上面提到的默认行为编写了我自己的自定义约束,然后才意识到我不必使用它,我将把它留在这里:
public class OptionalConstraint : IRouteConstraint
{
public OptionalConstraint(Regex regex)
{
this.Regex = regex;
}
public OptionalConstraint(string pattern) :
this(new Regex("^(" + pattern + ")$",
RegexOptions.CultureInvariant |
RegexOptions.Compiled |
RegexOptions.IgnoreCase)) { }
public Regex Regex { get; set; }
public bool Match(HttpContextBase httpContext,
Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection)
{
if(routeDirection == RouteDirection.IncomingRequest)
{
object value = values[parameterName];
if(value == UrlParameter.Optional)
return true;
if(this.Regex.IsMatch(value.ToString()))
return true;
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个示例路线:
routes.MapRoute("PostsByDate",
"{year}/{month}",
new { controller = "Posts",
action = "ByDate",
month = UrlParameter.Optional },
new { year = @"\d{4}",
month = new OptionalConstraint(@"\d\d") });
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
26414 次 |
| 最近记录: |