【翻译】ASP.NET MVC 5属性路由
2015-01-25 10:45
211 查看
原文链接:http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx#why-attribute-routing
最近在学习MVC相关的东西,今天刚好在msdn上看到了这样的一片文章,感觉不错,于是决定将它翻译出来和博友们一起分享下。我第一次发表文章,有不对的地方非常欢迎指出。
—— 写在前面
废话不多说了,咱们开始吧
路由是ASP.NET MVC 怎样去用一个URI去匹配一个Action 。MVC5 支持一个新类型的路由,叫做属性路由。就像这个名字所说的,属性路由用属性去定义路由。在我们的web 应用程序中,属性路由给了我们URI更多的控制权。
之前我们用的路由方式,叫做基本的约定路由,现在仍然完全支持。你也可以在同一个项目中结合两种技术。
这篇文章将覆盖ASP.NET MVC 5属性路由的基本特点以及怎样去使用
一、为什么需要属性路由
二、怎样去使用属性路由
三、可选的URI参数和默认路由
四、路由前缀
五、默认路由
六、路由约束以及自定义路由约束
七、给路由取个名字
八、区域(Areas)
映射到:
映射到:
映射到:
属性路由可以是我们更容易的去映射一个URI到一个Acion,上面的用属性路由我们就可以这样写:
我们也可以结合属性路由去对路由做一个基本的约束
在这个例子中/books 和/books/1430210079都可以去访问"View",前者是去返回所有的Book,而后者是返回指定的Book。
这时我们就可以通过[RoutePrefix]属性去为整个控制器设置一个共同的前缀
如果需要的话,你也可在Acion上用 “~" 去重写路由属性
这里例子,第一个路由仅当id是整数时,才被匹配;否则第二个路由将被匹配
下表列出了可支持的约束下表列出了可支持的约束
要注意一些约束,例如 min ,他的参数要用圆括号 ”()" 括起来
你也可以对一个参数用多个约束,用冒号 ":"隔开,例如
如果你想去指定一个参数可选的话就可以用 "?",他应该放到所有约束的最后面,代码如下:
那么我们应该怎样去用这个约束呢,看下面
先到路由配置里去注册这个约束
现在我们就可以直接在项目中用了,代码如下
哈哈,很爽吧
下面的链接最终生成的就是"/Admin/menu/show-options"了
如果我们在同时使用用Areas和属性路由,Areas的路由基于我们在AreaRegistration中设置的,你需要去确保在配置中Area注册是在MVC 属性路由注册之后,对于这两种配置,我们都应该在 默认路由之前去注册。原因我想我不用说都应该很清楚吧,哪一个先去注册,那一个路由配置就最先去匹配URI,匹配不成功再交给下一个路由配置,例如
终于翻译完了,由于这是本人是第一次翻译,英语水平也不太好,可能会有部分中式英语在里面以及一些其他不对的问题。如果有博友发现有问题我会立即更正的,谢谢!
原文链接在顶部已经贴出来了,有兴趣的也可以去看一下原文。
最近在学习MVC相关的东西,今天刚好在msdn上看到了这样的一片文章,感觉不错,于是决定将它翻译出来和博友们一起分享下。我第一次发表文章,有不对的地方非常欢迎指出。
—— 写在前面
废话不多说了,咱们开始吧
路由是ASP.NET MVC 怎样去用一个URI去匹配一个Action 。MVC5 支持一个新类型的路由,叫做属性路由。就像这个名字所说的,属性路由用属性去定义路由。在我们的web 应用程序中,属性路由给了我们URI更多的控制权。
之前我们用的路由方式,叫做基本的约定路由,现在仍然完全支持。你也可以在同一个项目中结合两种技术。
这篇文章将覆盖ASP.NET MVC 5属性路由的基本特点以及怎样去使用
一、为什么需要属性路由
二、怎样去使用属性路由
三、可选的URI参数和默认路由
四、路由前缀
五、默认路由
六、路由约束以及自定义路由约束
七、给路由取个名字
八、区域(Areas)
一、为什么需要属性路由
举个例子吧,在社会上比较好的的电商网站可能有如下的路由:{productId:int}/{productTitle}
映射到:
ProductsController.Show(int id)
{username}
映射到:
ProfilesController.Show(string username)
{username}/catalogs/{catalogId:int}/{catalogTitle}
映射到:
CatalogsController.Show(string username, int catalogId) (不在太在意这些特殊的语法,我们将在之后讲解中会涉及到)
在之前版本的ASP.NET MVC中,路由规则将在RouteConfig.cs文件中设置,它指出了真实的控制器和方法名,列如:
[code] routes.MapRoute(
name: "ProductPage",
url: "{productId}/{productTitle}",
defaults: new { controller = "Products", action = "Show" },
constraints: new { productId = "\\d+" }
);
属性路由可以是我们更容易的去映射一个URI到一个Acion,上面的用属性路由我们就可以这样写:
[Route("{productId:int}/{productTitle}")] public ActionResult Show(int productId) { ... }
二、怎样去使用属性路由
要去使用属性路由,必须先在到配置中去调用MapMvcAttributeRoutes
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapMvcAttributeRoutes(); } }
我们也可以结合属性路由去对路由做一个基本的约束
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapMvcAttributeRoutes(); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }
三、可选的URI参数和默认值
你可以通过增加一个 "?" 标记到路由参数上去使用一个可选的URI参数。可以通过 parameter=value指定一个默认的值public class BooksController : Controller { // eg: /books // eg: /books/1430210079 [Route("books/{isbn?}")] public ActionResult View(string isbn) { if (!String.IsNullOrEmpty(isbn)) { return View("OneBook", GetBook(isbn)); } return View("AllBooks", GetBooks()); } // eg: /books/lang // eg: /books/lang/en // eg: /books/lang/he [Route("books/lang/{lang=en}")] public ActionResult ViewByLanguage(string lang) { return View("OneBook", GetBooksByLanguage(lang)); } }
在这个例子中/books 和/books/1430210079都可以去访问"View",前者是去返回所有的Book,而后者是返回指定的Book。
四、路由前缀
通常在一个控制器中,都以相同的前缀开始,例如:public class ReviewsController : Controller { // eg: /reviews [Route("reviews")] public ActionResult Index() { ... } // eg: /reviews/5 [Route("reviews/{reviewId}")] public ActionResult Show(int reviewId) { ... } // eg: /reviews/5/edit [Route("reviews/{reviewId}/edit")] public ActionResult Edit(int reviewId) { ... } }
这时我们就可以通过[RoutePrefix]属性去为整个控制器设置一个共同的前缀
[RoutePrefix("reviews")] public class ReviewsController : Controller { // eg.: /reviews [Route] public ActionResult Index() { ... } // eg.: /reviews/5 [Route("{reviewId}")] public ActionResult Show(int reviewId) { ... } // eg.: /reviews/5/edit [Route("{reviewId}/edit")] public ActionResult Edit(int reviewId) { ... } }
如果需要的话,你也可在Acion上用 “~" 去重写路由属性
[RoutePrefix("reviews")] public class ReviewsController : Controller { // eg.: /spotlight-review [Route("~/spotlight-review")] public ActionResult ShowSpotlight() { ... } ... }
五、默认路由
我们也可以在一个Controller上去使用[Route],这个路由将被用在这个控制器所有的action上,除非一个指定的路由[Route]已经被用在一个action上(也就是重写了在这个Action的默认路由)。[RoutePrefix("promotions")] [Route("{action=index}")] public class ReviewsController : Controller { // eg.: /promotions public ActionResult Index() { ... } // eg.: /promotions/archive public ActionResult Archive() { ... } // eg.: /promotions/new public ActionResult New() { ... } // eg.: /promotions/edit/5 [Route("edit/{promoId:int}")] public ActionResult Edit(int promoId) { ... } }
六、路由约束
路由约束可以让我们去限制怎样去匹配路由参数,例如// eg: /users/5 [Route("users/{id:int}"] public ActionResult GetUserById(int id) { ... } // eg: users/ken [Route("users/{name}"] public ActionResult GetUserByName(string name) { ... }
这里例子,第一个路由仅当id是整数时,才被匹配;否则第二个路由将被匹配
下表列出了可支持的约束下表列出了可支持的约束
Constraint | Description | Example |
---|---|---|
alpha | Matches uppercase or lowercase Latin alphabet characters (a-z, A-Z) | {x:alpha} |
bool | Matches a Boolean value. | {x:bool} |
datetime | Matches a DateTime value. | {x:datetime} |
decimal | Matches a decimal value. | {x:decimal} |
double | Matches a 64-bit floating-point value. | {x:double} |
float | Matches a 32-bit floating-point value. | {x:float} |
guid | Matches a GUID value. | {x:guid} |
int | Matches a 32-bit integer value. | {x:int} |
length | Matches a string with the specified length or within a specified range of lengths. | {x:length(6)} {x:length(1,20)} |
long | Matches a 64-bit integer value. | {x:long} |
max | Matches an integer with a maximum value. | {x:max(10)} |
maxlength | Matches a string with a maximum length. | {x:maxlength(10)} |
min | Matches an integer with a minimum value. | {x:min(10)} |
minlength | Matches a string with a minimum length. | {x:minlength(10)} |
range | Matches an integer within a range of values. | {x:range(10,50)} |
regex | Matches a regular expression. | {x:regex(^\d{3}-\d{3}-\d{4}$)} |
你也可以对一个参数用多个约束,用冒号 ":"隔开,例如
// eg: /users/5 // but not /users/10000000000 because it is larger than int.MaxValue, // and not /users/0 because of the min(1) constraint. [Route("users/{id:int:min(1)}")] public ActionResult GetUserById(int id) { ... }
如果你想去指定一个参数可选的话就可以用 "?",他应该放到所有约束的最后面,代码如下:
// eg: /greetings/bye // and /greetings because of the Optional modifier, // but not /greetings/see-you-tomorrow because of the maxlength(3) constraint. [Route("greetings/{message:maxlength(3)?}")] public ActionResult Greet(string message) { ... }
七、自定义约束
我们也可以通过实现IRouteConstraint接口创建一个自定义的路由约束,下面的一个例子,自定义一个约束去限制用户顺便输入一个参数public class ValuesConstraint : IRouteConstraint { private readonly string[] validOptions; public ValuesConstraint(string options) { validOptions = options.Split('|'); } public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) { object value; if (values.TryGetValue(parameterName, out value) && value != null) { return validOptions.Contains(value.ToString(), StringComparer.OrdinalIgnoreCase); } return false; } }
那么我们应该怎样去用这个约束呢,看下面
先到路由配置里去注册这个约束
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); var constraintsResolver = new DefaultInlineConstraintResolver(); constraintsResolver.ConstraintMap.Add("values", typeof(ValuesConstraint)); routes.MapMvcAttributeRoutes(constraintsResolver); } }
现在我们就可以直接在项目中用了,代码如下
public class TemperatureController : Controller { // eg: temp/celsius and /temp/fahrenheit but not /temp/kelvin [Route("temp/{scale:values(celsius|fahrenheit)}")] public ActionResult Show(string scale) { return Content("scale is " + scale); } }
八、路由名字
我们也可以为路由指定一个名字,这样可以方便我们去生成它[Route("menu", Name = "mainmenu")] public ActionResult MainMenu() { ... }
<a href="@Url.RouteUrl("mainmenu")">Main menu</a>
哈哈,很爽吧
九、Areas
我们可以使用RouteArea属性,去让控制器属于一个Area
[RouteArea("Admin")] [RoutePrefix("menu")] [Route("{action}")] public class MenuController : Controller { // eg: /admin/menu/login public ActionResult Login() { ... } // eg: /admin/menu/show-options [Route("show-options")] public ActionResult Options() { ... } // eg: /stats [Route("~/stats")] public ActionResult Stats() { ... } }
下面的链接最终生成的就是"/Admin/menu/show-options"了
Url.Action("Options", "Menu", new { Area = "Admin" })
如果我们在同时使用用Areas和属性路由,Areas的路由基于我们在AreaRegistration中设置的,你需要去确保在配置中Area注册是在MVC 属性路由注册之后,对于这两种配置,我们都应该在 默认路由之前去注册。原因我想我不用说都应该很清楚吧,哪一个先去注册,那一个路由配置就最先去匹配URI,匹配不成功再交给下一个路由配置,例如
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapMvcAttributeRoutes(); AreaRegistration.RegisterAllAreas(); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }
终于翻译完了,由于这是本人是第一次翻译,英语水平也不太好,可能会有部分中式英语在里面以及一些其他不对的问题。如果有博友发现有问题我会立即更正的,谢谢!
原文链接在顶部已经贴出来了,有兴趣的也可以去看一下原文。
相关文章推荐
- 【翻译】ASP.NET MVC 5属性路由(转)
- 运用路由约束 使用属性路由 精通ASP-NET-MVC-5-弗瑞曼
- 使用Route Prefix 使用属性路由 精通ASP-NET-MVC-5-弗瑞曼
- [翻译]《ASP.NET MVC 3 高级编程》第九章:路由(Professional ASP.NET MVC 3 --- Chapter 9: Routing)
- [翻译] ASP.NET MVC Tip #13 – 对自定义路由进行单元测试
- 《Entity Framework 6 Recipes》中文翻译系列 (21) -----第四章 ASP.NET MVC中使用实体框架之在页面中创建查询和使用ASP.NET URL路由过虑
- 指定HTML标签属性 |Specifying HTML Attributes| 在视图中生成输出URL |高级路由特性 | 精通ASP-NET-MVC-5-弗瑞曼
- [翻译]ASP.NET MVC 3 开发的20个秘诀(十九)[20 Recipes for Programming MVC 3]:路由用户至特定的Controller或Action
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第五章:排序、分页和路由
- [翻译:ASP.NET MVC 教程]创建路由约束
- [翻译:ASP.NET MVC 教程]创建路由约束
- [翻译:ASP.NET MVC 教程]创建自定义路由约束
- [翻译:ASP.NET MVC 教程]创建自定义路由
- [翻译]ASP.NET MVC CodePlex Preview 5 更新细节(未完成)
- [翻译]ASP.NET MVC Tip #39 – 在ASP.NET MVC中使用分布式缓存
- 把ASP.NET MVC的路由利用配置维护起来
- [翻译] ASP.NET MVC Tip #10 - 防止URL操作攻击
- [翻译]在ASP.NET MVC中使用TDD与依赖注入
- [翻译] ASP.NET MVC Tip #8 – 创建ASP.NET MVC GridView辅助方法