在StackOverflow播客#54中,Jeff提到他们通过处理路由的方法上方的属性在StackOverflow代码库中注册其URL路由.听起来像一个很好的概念(菲尔哈克提出的关于路线优先事项的警告).
有人可以提供一些样本来实现这一目标吗?
此外,使用这种路由风格的任何"最佳实践"?
更新:这已发布在 codeplex上.完整的源代码以及预编译的程序集可供下载.我还没有时间在网站上发布文档,所以这篇SO帖子现在已经足够了.
更新:我添加了一些新属性来处理1)路由排序,2)路由参数约束,以及3)路由参数默认值.以下文字反映了此更新.
我实际上已经为我的MVC项目做了类似的事情(我不知道Jeff是如何使用stackoverflow做的).我定义了一组自定义属性:UrlRoute,UrlRouteParameterConstraint,UrlRouteParameterDefault.它们可以附加到MVC控制器操作方法,以使路由,约束和默认值自动绑定到它们.
用法示例:
(注意这个例子有点做作,但它演示了这个特性)
public class UsersController : Controller { // Simple path. // Note you can have multiple UrlRoute attributes affixed to same method. [UrlRoute(Path = "users")] public ActionResult Index() { return View(); } // Path with parameter plus constraint on parameter. // You can have multiple constraints. [UrlRoute(Path = "users/{userId}")] [UrlRouteParameterConstraint(Name = "userId", Regex = @"\d+")] public ActionResult UserProfile(int userId) { // ...code omitted return View(); } // Path with Order specified, to ensure it is added before the previous // route. Without this, the "users/admin" URL may match the previous // route before this route is even evaluated. [UrlRoute(Path = "users/admin", Order = -10)] public ActionResult AdminProfile() { // ...code omitted return View(); } // Path with multiple parameters and default value for the last // parameter if its not specified. [UrlRoute(Path = "users/{userId}/posts/{dateRange}")] [UrlRouteParameterConstraint(Name = "userId", Regex = @"\d+")] [UrlRouteParameterDefault(Name = "dateRange", Value = "all")] public ActionResult UserPostsByTag(int userId, string dateRange) { // ...code omitted return View(); }
UrlRouteAttribute的定义:
////// Assigns a URL route to an MVC Controller class method. /// [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class UrlRouteAttribute : Attribute { ////// Optional name of the route. If not specified, the route name will /// be set to [controller name].[action name]. /// public string Name { get; set; } ////// Path of the URL route. This is relative to the root of the web site. /// Do not append a "/" prefix. Specify empty string for the root page. /// public string Path { get; set; } ////// Optional order in which to add the route (default is 0). Routes /// with lower order values will be added before those with higher. /// Routes that have the same order value will be added in undefined /// order with respect to each other. /// public int Order { get; set; } }
UrlRouteParameterConstraintAttribute的定义:
////// Assigns a constraint to a route parameter in a UrlRouteAttribute. /// [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class UrlRouteParameterConstraintAttribute : Attribute { ////// Name of the route parameter on which to apply the constraint. /// public string Name { get; set; } ////// Regular expression constraint to test on the route parameter value /// in the URL. /// public string Regex { get; set; } }
UrlRouteParameterDefaultAttribute的定义:
////// Assigns a default value to a route parameter in a UrlRouteAttribute /// if not specified in the URL. /// [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class UrlRouteParameterDefaultAttribute : Attribute { ////// Name of the route parameter for which to supply the default value. /// public string Name { get; set; } ////// Default value to set on the route parameter if not specified in the URL. /// public object Value { get; set; } }
对Global.asax.cs的更改:
将调用替换为MapRoute,只需调用RouteUtility.RegisterUrlRoutesFromAttributes函数:
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); RouteUtility.RegisterUrlRoutesFromAttributes(routes); }
RouteUtility.RegisterUrlRoutesFromAttributes的定义:
完整的源代码在codeplex上.如果您有任何反馈或错误报告,请访问该网站.
您也可以尝试AttributeRouting,它可以从github上或通过的NuGet.
这是一个无耻的插件,因为我是项目作者.但是,如果我不是很高兴使用它.你可能也是.github存储库wiki中有大量文档和示例代码.
有了这个库,你可以做很多事情:
使用GET,POST,PUT和DELETE属性装饰您的操作.
将多个路由映射到单个操作,使用Order属性对它们进行排序.
使用属性指定路由默认值和约束.
用简单的方法指定可选参数?参数名称前的标记.
指定支持命名路由的路由名称.
在控制器或基本控制器上定义MVC区域.
使用应用于控制器或基本控制器的路由前缀将路由组合或嵌套在一起.
支持旧网址.
在控制器内以及控制器和基本控制器之间设置为操作定义的路由之间的路由优先级.
自动生成小写的出站URL.
定义您自己的自定义路由约定并将其应用于控制器,以便在没有样板属性的情况下为控制器内的操作生成路径(请考虑RESTful样式).
使用提供的HttpHandler调试路由.
我确定还有其他一些我忘了的东西.看看这个.通过nuget安装很轻松.
注意:截至4/16/12,AttributeRouting还支持新的Web API基础结构.以防你正在寻找可以处理的东西.谢谢subkamran!
1.下载RiaLibrary.Web.dll并在ASP.NET MVC网站项目中引用它
2.使用[Url]属性解压缩控制器方法:
public SiteController : Controller { [Url("")] public ActionResult Home() { return View(); } [Url("about")] public ActionResult AboutUs() { return View(); } [Url("store/{?category}")] public ActionResult Products(string category = null) { return View(); } }
顺便说一句,'?' 登录'{?category}'参数意味着它是可选的.您不需要在路由默认值中明确指定它,这等于:
routes.MapRoute("Store", "store/{category}", new { controller = "Store", action = "Home", category = UrlParameter.Optional });
3.更新Global.asax.cs文件
public class MvcApplication : System.Web.HttpApplication { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoutes(); // This does the trick } protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } }
如何设置默认值和约束?例:
public SiteController : Controller { [Url("admin/articles/edit/{id}", Constraints = @"id=\d+")] public ActionResult ArticlesEdit(int id) { return View(); } [Url("articles/{category}/{date}_{title}", Constraints = "date=(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")] public ActionResult Article(string category, DateTime date, string title) { return View(); } }
如何订购?例:
[Url("forums/{?category}", Order = 2)] public ActionResult Threads(string category) { return View(); } [Url("forums/new", Order = 1)] public ActionResult NewThread() { return View(); }