asp.net-mvc 通过方法属性的 ASP.NET MVC 路由
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/894779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ASP.NET MVC Routing Via Method Attributes
提问by TorgoGuy
In the StackOverflow Podcast #54, Jeff mentions they register their URL routes in the StackOverflow codebase via an attribute above the method that handles the route. Sounds like a good concept (with the caveat that Phil Haack brought up regarding route priorities).
在StackOverflow Podcast #54 中,Jeff 提到他们通过处理路由的方法上方的属性在 StackOverflow 代码库中注册了他们的 URL 路由。听起来是个不错的概念(Phil Haack 提出了关于路由优先级的警告)。
Could someone provide some sample to make this happen?
有人可以提供一些样本来实现这一目标吗?
Also, any "best practices" for using this style of routing?
此外,使用这种路由风格的任何“最佳实践”?
采纳答案by DSO
UPDATE: This has been posted on codeplex. The complete source code as well as the pre-compiled assembly are there for download. I haven't had time to post the documentation on the site yet, so this SO post will have to suffice for now.
更新:这已发布在codeplex 上。完整的源代码以及预编译的程序集都可以下载。我还没有时间在网站上发布文档,所以这个 SO 帖子现在就足够了。
UPDATE: I added some new attributes to handle 1) route ordering, 2) route parameter constraints, and 3) route parameter default values. The text below reflects this update.
更新:我添加了一些新属性来处理 1) 路由排序、2) 路由参数约束和 3) 路由参数默认值。下面的文字反映了这一更新。
I've actually done something like this for my MVC projects (I have no idea how Jeff is doing it with stackoverflow). I defined a set of custom attributes: UrlRoute, UrlRouteParameterConstraint, UrlRouteParameterDefault. They can be attached to MVC controller action methods to cause routes, constraints, and defaults to be bound to them automatically.
我实际上已经为我的 MVC 项目做了这样的事情(我不知道杰夫是如何用 stackoverflow 做到的)。我定义了一组自定义属性:UrlRoute、UrlRouteParameterConstraint、UrlRouteParameterDefault。它们可以附加到 MVC 控制器操作方法,以自动将路由、约束和默认值绑定到它们。
Example usage:
用法示例:
(Note this example is somewhat contrived but it demonstrates the feature)
(请注意,此示例有些人为,但它演示了该功能)
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();
}
Definition of UrlRouteAttribute:
UrlRouteAttribute 的定义:
/// <summary>
/// Assigns a URL route to an MVC Controller class method.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class UrlRouteAttribute : Attribute
{
/// <summary>
/// Optional name of the route. If not specified, the route name will
/// be set to [controller name].[action name].
/// </summary>
public string Name { get; set; }
/// <summary>
/// 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.
/// </summary>
public string Path { get; set; }
/// <summary>
/// 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.
/// </summary>
public int Order { get; set; }
}
Definition of UrlRouteParameterConstraintAttribute:
UrlRouteParameterConstraintAttribute 的定义:
/// <summary>
/// Assigns a constraint to a route parameter in a UrlRouteAttribute.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class UrlRouteParameterConstraintAttribute : Attribute
{
/// <summary>
/// Name of the route parameter on which to apply the constraint.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Regular expression constraint to test on the route parameter value
/// in the URL.
/// </summary>
public string Regex { get; set; }
}
Definition of UrlRouteParameterDefaultAttribute:
UrlRouteParameterDefaultAttribute 的定义:
/// <summary>
/// Assigns a default value to a route parameter in a UrlRouteAttribute
/// if not specified in the URL.
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class UrlRouteParameterDefaultAttribute : Attribute
{
/// <summary>
/// Name of the route parameter for which to supply the default value.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Default value to set on the route parameter if not specified in the URL.
/// </summary>
public object Value { get; set; }
}
Changes to Global.asax.cs:
Global.asax.cs 的变化:
Replace calls to MapRoute, with a single call to the RouteUtility.RegisterUrlRoutesFromAttributes function:
使用对 RouteUtility.RegisterUrlRoutesFromAttributes 函数的单个调用替换对 MapRoute 的调用:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
RouteUtility.RegisterUrlRoutesFromAttributes(routes);
}
Definition of RouteUtility.RegisterUrlRoutesFromAttributes:
RouteUtility.RegisterUrlRoutesFromAttributes 的定义:
The full source is up on codeplex. Please go to the site if you have any feedback or bug reports.
完整的源代码在codeplex 上。如果您有任何反馈或错误报告,请访问该站点。
回答by spot
You can also try AttributeRouting, which is available from githubor via nuget.
您还可以尝试AttributeRouting,它可以从github或通过nuget 获得。
This is a shameless plug, as I am the project author. But dang if I'm not very happy using it. You might be too. There is plenty of documentation and sample code in the github repository wiki.
这是一个无耻的插件,因为我是项目作者。但是如果我对使用它不是很满意,那就太糟糕了。你可能也是。github 存储库wiki 中有大量文档和示例代码。
With this library, you can do a lot:
有了这个库,你可以做很多事情:
- Decorate your actions with GET, POST, PUT, and DELETE attributes.
- Map multiple routes to a single action, ordering them with an Order property.
- Specify route defaults and constraints using attributes.
- Specify optional params with a simple ? token before the parameter name.
- Specify the route name for supporting named routes.
- Define MVC areas on a controller or base controller.
- Group or nest your routes together using route prefixes applied to a controller or base controller.
- Support legacy urls.
- Set the precedence of routes among the routes defined for an action, within a controller, and among controllers and base controllers.
- Generate lowercase outbound urls automatically.
- Define your own custom route conventions and apply them on a controller to generate the routes for actions within the controller without boilerplate attributes (think RESTful style).
- Debug your routes using a supplied HttpHandler.
- 使用 GET、POST、PUT 和 DELETE 属性装饰您的操作。
- 将多个路由映射到单个操作,使用 Order 属性对它们进行排序。
- 使用属性指定路由默认值和约束。
- 使用简单的 ? 参数名称前的标记。
- 指定支持命名路由的路由名称。
- 在控制器或基本控制器上定义 MVC 区域。
- 使用应用于控制器或基本控制器的路由前缀将您的路由组合或嵌套在一起。
- 支持旧网址。
- 设置为操作定义的路由之间、控制器内以及控制器和基本控制器之间的路由优先级。
- 自动生成小写的出站网址。
- 定义您自己的自定义路由约定并将它们应用到控制器上,以在没有样板属性的情况下为控制器内的操作生成路由(想想 RESTful 风格)。
- 使用提供的 HttpHandler 调试您的路由。
I'm sure there's some other stuff I'm forgetting. Check it out. It's painless to install via nuget.
我确定还有一些其他的东西我忘记了。一探究竟。通过 nuget 安装很轻松。
NOTE: As of 4/16/12, AttributeRouting also supports the new Web API infrastructure.Just in case you're looking for something that can handle that. Thanks subkamran!
注意:截至 2012 年 4 月 16 日,AttributeRouting 还支持新的 Web API 基础结构。以防万一你正在寻找可以处理的东西。谢谢苏卡姆兰!
回答by Konstantin Tarkus
1. Download RiaLibrary.Web.dlland reference it in your ASP.NET MVC website project
1. 下载RiaLibrary.Web.dll并在您的 ASP.NET MVC 网站项目中引用它
2. Decoreate controller methods with the [Url] Attributes:
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();
}
}
BTW, '?' sign in '{?category}' parameter means that it's optional. You won't need to specify this explicitly in route defaults, which is equals to this:
顺便提一句, '?' 登录 '{?category}' 参数意味着它是可选的。您不需要在路由默认值中明确指定它,它等于:
routes.MapRoute("Store", "store/{category}",
new { controller = "Store", action = "Home", category = UrlParameter.Optional });
3. Update Global.asax.cs file
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);
}
}
How to set defaults and constraints? Example:
如何设置默认值和约束?例子:
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();
}
}
How to set ordering? Example:
如何设置排序?例子:
[Url("forums/{?category}", Order = 2)]
public ActionResult Threads(string category)
{
return View();
}
[Url("forums/new", Order = 1)]
public ActionResult NewThread()
{
return View();
}
回答by Nicolas Cadilhac
This post is just to extend DSO's answer.
这篇文章只是为了扩展 DSO 的答案。
While converting my routes to attributes, I needed to handle the ActionName attribute. So in GetRouteParamsFromAttribute:
在将我的路由转换为属性时,我需要处理 ActionName 属性。所以在 GetRouteParamsFromAttribute 中:
ActionNameAttribute anAttr = methodInfo.GetCustomAttributes(typeof(ActionNameAttribute), false)
.Cast<ActionNameAttribute>()
.SingleOrDefault();
// Add to list of routes.
routeParams.Add(new MapRouteParams()
{
RouteName = routeAttrib.Name,
Path = routeAttrib.Path,
ControllerName = controllerName,
ActionName = (anAttr != null ? anAttr.Name : methodInfo.Name),
Order = routeAttrib.Order,
Constraints = GetConstraints(methodInfo),
Defaults = GetDefaults(methodInfo),
});
Also I found the naming of the route not suitable. The name is built dynamically with controllerName.RouteName. But my route names are const strings in the controller class and I use those const to also call Url.RouteUrl. That's why I really need the route name in the attribute to be the actual name of the route.
我还发现路线的命名不合适。该名称是使用 controllerName.RouteName 动态构建的。但是我的路由名称是控制器类中的常量字符串,我使用这些常量来调用 Url.RouteUrl。这就是为什么我真的需要属性中的路由名称作为路由的实际名称。
Another thing that I will do is to convert the default and constraint attributes to AttributeTargets.Parameter so that I can stick them to params.
我要做的另一件事是将默认和约束属性转换为 AttributeTargets.Parameter,以便我可以将它们粘贴到 params。
回答by Max Metral
I've combined these two approaches into a Frankensteinian version for anybody who wants it. (I liked the optional param notation, but also thought they should be separate attributes from default/constraints rather than all mixed into one).
我已经将这两种方法组合成一个弗兰肯斯坦版本,供任何想要它的人使用。(我喜欢可选的参数符号,但也认为它们应该是与默认/约束分开的属性,而不是全部混合在一起)。
http://github.com/djMax/AlienForce/tree/master/Utilities/Web/
http://github.com/djMax/AlienForce/tree/master/Utilities/Web/
回答by TimDog
I needed to get the ITCloud routing working in asp.net mvc 2 using an AsyncController -- to do so, just edit the RouteUtility.cs class in the source and recompile. You have to strip off the "Completed" from the action name on line 98
我需要使用 AsyncController 使 ITCloud 路由在 asp.net mvc 2 中工作——为此,只需编辑源代码中的 RouteUtility.cs 类并重新编译。您必须从第 98 行的操作名称中去除“已完成”
// Add to list of routes.
routeParams.Add(new MapRouteParams()
{
RouteName = String.IsNullOrEmpty(routeAttrib.Name) ? null : routeAttrib.Name,
Path = routeAttrib.Path,
ControllerName = controllerName,
ActionName = methodInfo.Name.Replace("Completed", ""),
Order = routeAttrib.Order,
Constraints = GetConstraints(methodInfo),
Defaults = GetDefaults(methodInfo),
ControllerNamespace = controllerClass.Namespace,
});
Then, in the AsyncController, decorate the XXXXCompleted ActionResult with the familiar UrlRouteand UrlRouteParameterDefaultattributes:
然后,在 AsyncController 中,使用熟悉的UrlRoute和UrlRouteParameterDefault属性装饰 XXXXCompleted ActionResult :
[UrlRoute(Path = "ActionName/{title}")]
[UrlRouteParameterDefault(Name = "title", Value = "latest-post")]
public ActionResult ActionNameCompleted(string title)
{
...
}
Hope that helps someone with the same issue.
希望能帮助有同样问题的人。

