转载链接:http://www.cnblogs.com/thestartdream/p/4246533.html

原文链接: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)

一、为什么需要属性路由

举个例子吧,在社会上比较好的的电商网站可能有如下的路由:

    • {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文件中设置,它指出了真实的控制器和方法名,列如:

  1. 1 routes.MapRoute(
  2. 2 name: "ProductPage",
  3. 3 url: "{productId}/{productTitle}",
  4. 4 defaults: new { controller = "Products", action = "Show" },
  5. 5 constraints: new { productId = "\\d+" }
  6. 6 );

属性路由可以是我们更容易的去映射一个URI到一个Acion,上面的用属性路由我们就可以这样写:

  1. 1 [Route("{productId:int}/{productTitle}")]
  2. 2 public ActionResult Show(int productId) { ... }

二、怎样去使用属性路由

要去使用属性路由,必须先在到配置中去调用MapMvcAttributeRoutes

  1. 1 public class RouteConfig
  2. 2 {
  3. 3 public static void RegisterRoutes(RouteCollection routes)
  4. 4 {
  5. 5 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  6. 6
  7. 7 routes.MapMvcAttributeRoutes();
  8. 8 }
  9. 9 }

我们也可以结合属性路由去对路由做一个基本的约束

  1. public static void RegisterRoutes(RouteCollection routes)
  2. {
  3. routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  4.  
  5. routes.MapMvcAttributeRoutes();
  6.  
  7. routes.MapRoute(
  8. name: "Default",
  9. url: "{controller}/{action}/{id}",
  10. defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
  11. );
  12. }

三、可选的URI参数和默认值

你可以通过增加一个 "?" 标记到路由参数上去使用一个可选的URI参数。可以通过 parameter=value指定一个默认的值

  1. 1 public class BooksController : Controller
  2. 2 {
  3. 3 // eg: /books
  4. 4 // eg: /books/1430210079
  5. 5 [Route("books/{isbn?}")]
  6. 6 public ActionResult View(string isbn)
  7. 7 {
  8. 8 if (!String.IsNullOrEmpty(isbn))
  9. 9 {
  10. 10 return View("OneBook", GetBook(isbn));
  11. 11 }
  12. 12 return View("AllBooks", GetBooks());
  13. 13 }
  14. 14
  15. 15 // eg: /books/lang
  16. 16 // eg: /books/lang/en
  17. 17 // eg: /books/lang/he
  18. 18 [Route("books/lang/{lang=en}")]
  19. 19 public ActionResult ViewByLanguage(string lang)
  20. 20 {
  21. 21 return View("OneBook", GetBooksByLanguage(lang));
  22. 22 }
  23. 23 }

在这个例子中/books 和/books/1430210079都可以去访问"View",前者是去返回所有的Book,而后者是返回指定的Book。

四、路由前缀

通常在一个控制器中,都以相同的前缀开始,例如:

  1. 1 public class ReviewsController : Controller
  2. 2 {
  3. 3 // eg: /reviews
  4. 4 [Route("reviews")]
  5. 5 public ActionResult Index() { ... }
  6. 6 // eg: /reviews/5
  7. 7 [Route("reviews/{reviewId}")]
  8. 8 public ActionResult Show(int reviewId) { ... }
  9. 9 // eg: /reviews/5/edit
  10. 10 [Route("reviews/{reviewId}/edit")]
  11. 11 public ActionResult Edit(int reviewId) { ... }
  12. 12 }

这时我们就可以通过[RoutePrefix]属性去为整个控制器设置一个共同的前缀

  1. 1 [RoutePrefix("reviews")]
  2. 2 public class ReviewsController : Controller
  3. 3 {
  4. 4 // eg.: /reviews
  5. 5 [Route]
  6. 6 public ActionResult Index() { ... }
  7. 7 // eg.: /reviews/5
  8. 8 [Route("{reviewId}")]
  9. 9 public ActionResult Show(int reviewId) { ... }
  10. 10 // eg.: /reviews/5/edit
  11. 11 [Route("{reviewId}/edit")]
  12. 12 public ActionResult Edit(int reviewId) { ... }
  13. 13 }

如果需要的话,你也可在Acion上用 “~" 去重写路由属性

  1. 1 [RoutePrefix("reviews")]
  2. 2 public class ReviewsController : Controller
  3. 3 {
  4. 4 // eg.: /spotlight-review
  5. 5 [Route("~/spotlight-review")]
  6. 6 public ActionResult ShowSpotlight() { ... }
  7. 7
  8. 8 ...
  9. 9 }

五、默认路由

我们也可以在一个Controller上去使用[Route],这个路由将被用在这个控制器所有的action上,除非一个指定的路由[Route]已经被用在一个action上(也就是重写了在这个Action的默认路由)。

  1. 1 [RoutePrefix("promotions")]
  2. 2 [Route("{action=index}")]
  3. 3 public class ReviewsController : Controller
  4. 4 {
  5. 5 // eg.: /promotions
  6. 6 public ActionResult Index() { ... }
  7. 7
  8. 8 // eg.: /promotions/archive
  9. 9 public ActionResult Archive() { ... }
  10. 10
  11. 11 // eg.: /promotions/new
  12. 12 public ActionResult New() { ... }
  13. 13
  14. 14 // eg.: /promotions/edit/5
  15. 15 [Route("edit/{promoId:int}")]
  16. 16 public ActionResult Edit(int promoId) { ... }
  17. 17 }

六、路由约束

路由约束可以让我们去限制怎样去匹配路由参数,例如

  1. 1 // eg: /users/5
  2. 2 [Route("users/{id:int}"]
  3. 3 public ActionResult GetUserById(int id) { ... }
  4. 4
  5. 5 // eg: users/ken
  6. 6 [Route("users/{name}"]
  7. 7 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}$)}

要注意一些约束,例如 min ,他的参数要用圆括号 ”()" 括起来
  你也可以对一个参数用多个约束,用冒号 ":"隔开,例如

  1. 1 // eg: /users/5
  2. 2 // but not /users/10000000000 because it is larger than int.MaxValue,
  3. 3 // and not /users/0 because of the min(1) constraint.
  4. 4 [Route("users/{id:int:min(1)}")]
  5. 5 public ActionResult GetUserById(int id) { ... }

如果你想去指定一个参数可选的话就可以用 "?",他应该放到所有约束的最后面,代码如下:

  1. 1 // eg: /greetings/bye
  2. 2 // and /greetings because of the Optional modifier,
  3. 3 // but not /greetings/see-you-tomorrow because of the maxlength(3) constraint.
  4. 4 [Route("greetings/{message:maxlength(3)?}")]
  5. 5 public ActionResult Greet(string message) { ... }

七、自定义约束

我们也可以通过实现IRouteConstraint接口创建一个自定义的路由约束,下面的一个例子,自定义一个约束去限制用户顺便输入一个参数

  1. 1 public class ValuesConstraint : IRouteConstraint
  2. 2 {
  3. 3 private readonly string[] validOptions;
  4. 4 public ValuesConstraint(string options)
  5. 5 {
  6. 6 validOptions = options.Split('|');
  7. 7 }
  8. 8
  9. 9 public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
  10. 10 {
  11. 11 object value;
  12. 12 if (values.TryGetValue(parameterName, out value) && value != null)
  13. 13 {
  14. 14 return validOptions.Contains(value.ToString(), StringComparer.OrdinalIgnoreCase);
  15. 15 }
  16. 16 return false;
  17. 17 }
  18. 18 }

那么我们应该怎样去用这个约束呢,看下面

先到路由配置里去注册这个约束

  1. 1 public class RouteConfig
  2. 2 {
  3. 3 public static void RegisterRoutes(RouteCollection routes)
  4. 4 {
  5. 5 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  6. 6
  7. 7 var constraintsResolver = new DefaultInlineConstraintResolver();
  8. 8
  9. 9 constraintsResolver.ConstraintMap.Add("values", typeof(ValuesConstraint));
  10. 10
  11. 11 routes.MapMvcAttributeRoutes(constraintsResolver);
  12. 12 }
  13. 13 }

现在我们就可以直接在项目中用了,代码如下

  1. 1 public class TemperatureController : Controller
  2. 2 {
  3. 3 // eg: temp/celsius and /temp/fahrenheit but not /temp/kelvin
  4. 4 [Route("temp/{scale:values(celsius|fahrenheit)}")]
  5. 5 public ActionResult Show(string scale)
  6. 6 {
  7. 7 return Content("scale is " + scale);
  8. 8 }
  9. 9 }

八、路由名字

我们也可以为路由指定一个名字,这样可以方便我们去生成它

  1. 1 [Route("menu", Name = "mainmenu")]
  2. 2 public ActionResult MainMenu() { ... }
  1. 1 <a href="@Url.RouteUrl("mainmenu")">Main menu</a>

哈哈,很爽吧

九、Areas

我们可以使用RouteArea属性,去让控制器属于一个Area

  1. 1 [RouteArea("Admin")]
  2. 2 [RoutePrefix("menu")]
  3. 3 [Route("{action}")]
  4. 4 public class MenuController : Controller
  5. 5 {
  6. 6 // eg: /admin/menu/login
  7. 7 public ActionResult Login() { ... }
  8. 8
  9. 9 // eg: /admin/menu/show-options
  10. 10 [Route("show-options")]
  11. 11 public ActionResult Options() { ... }
  12. 12
  13. 13 // eg: /stats
  14. 14 [Route("~/stats")]
  15. 15 public ActionResult Stats() { ... }
  16. 16 }

下面的链接最终生成的就是"/Admin/menu/show-options"了

  1. 1 Url.Action("Options", "Menu", new { Area = "Admin" })

如果我们在同时使用用Areas和属性路由,Areas的路由基于我们在AreaRegistration中设置的,你需要去确保在配置中Area注册是在MVC 属性路由注册之后,对于这两种配置,我们都应该在 默认路由之前去注册。原因我想我不用说都应该很清楚吧,哪一个先去注册,那一个路由配置就最先去匹配URI,匹配不成功再交给下一个路由配置,例如

  1. 1 public static void RegisterRoutes(RouteCollection routes)
  2. 2 {
  3. 3 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  4. 4
  5. 5 routes.MapMvcAttributeRoutes();
  6. 6
  7. 7 AreaRegistration.RegisterAllAreas();
  8. 8
  9. 9 routes.MapRoute(
  10. 10 name: "Default",
  11. 11 url: "{controller}/{action}/{id}",
  12. 12 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
  13. 13 );
  14. 14 }

终于翻译完了,由于这是本人是第一次翻译,英语水平也不太好,可能会有部分中式英语在里面以及一些其他不对的问题。如果有博友发现有问题我会立即更正的,谢谢!

原文链接在顶部已经贴出来了,有兴趣的也可以去看一下原文。

【翻译】ASP.NET MVC 5属性路由(转)的更多相关文章

  1. 为ASP.NET MVC应用添加自定义路由

    这里,我们将学习如何给asp.net mvc应用添加自定义路由.用自定义路由来修改默认路由表. 对一些简单的asp.net mvc应用,默认的路由表就已经足够了.但是,当你需要创建特殊的路由时,就需要 ...

  2. 探索ASP.NET MVC框架之路由系统

    引言 对于ASP.NET MVC的路由系统相信大家肯定不陌生.今天我们就深入ASP.NET的框架内部来看一下路由系统到底是怎么通过我们给出的地址(例如:/Home/Index)解析出Controlle ...

  3. MVC 5 属性路由中添加自己的自定义约束

    介绍约束 ASP.NET MVC和web api 同时支持简单和自定义约束,简单的约束看起来像: routes.MapRoute("blog", "{year}/{mon ...

  4. Asp.net mvc 中的路由

    在 Asp.net mvc 中,来自客户端的请求总是针对某个 Controller 中的 Action 方法,因此,必须采用某种机制从请求的 URl 中解析出对应的 Controller 和 Acti ...

  5. ASP.NET MVC教程五:ASP.NET MVC中的路由

    一.概述 在ASP.NET MVC架构中,控制器在3大核心构件中处于中心地位,通过控制器支配模型和视图,然而从浏览器发出的请求到控制器还需要路由的协助,路由将特定的请求和控制器的动作对应起来. 在AS ...

  6. 第2章 ASP.NET MVC(URL、路由及区域)

    * { font: 17px/1.5em "Microsoft YaHei" } ASPNET MVC URL.路由及区域 一.URL.路由及区域 一.      配置路由器 1. ...

  7. ASP.NET MVC 学习之路由(URL Routing)

    在ASP.NET MVC中,一个URL请求是由对应的一个Controller中的Action来处理的,由URL Routing来告诉MVC如何定位到正确的Controller和Action. 默认路由 ...

  8. Asp.net Mvc 多级控制器 路由重写 及 多级Views目录 的寻找视图的规则 (多级路由) 如:Admin/Test/Index

    http://blog.csdn.net/buhuan123/article/details/26387427 目录(?)[-] 1那么我们再来看我们需要的访问方式如下图 razor视图的地址写成通配 ...

  9. ASP.NET MVC 的URL路由介绍

    在这个教程中,向你介绍每个ASP.NET MVC一个重要的特点叫做URL路由.URL路由模块是负责映射从浏览器请求到特定的控制器动作. 在教程的第一部分,你将学习标准路由表如何映射到控制器的动作.在教 ...

随机推荐

  1. VS使用技巧——统计代码行数

    通常为了统计一个文件或者一整个解决管理方案中代码行量,可能会选择定位来获取行量,但是当文件尤其大时,传统方式就不行了,这里推荐使用正则表达式搜索统计,可以快速获取目标文档的总代码量. Tips: ct ...

  2. chkdsk磁盘修复命令工具怎么用,怎样运行chkdsk工具修复?

    Chkdsk是系统检查磁盘当前状态的一个命令,启动它可以显示磁盘状态.内存状态和指定路径下指定文件的不连续数目.选择“开始→运行”输入“Chkdsk”回车,即可启动Chkdsk,它会自动校验文件并将丢 ...

  3. GitHub 上 57 款最流行的开源深度学习项目

    转载:https://www.oschina.net/news/79500/57-most-popular-deep-learning-project-at-github GitHub 上 57 款最 ...

  4. 前端相关html和css

    #请参考http://www.cnblogs.com/pycode/p/5792142.html #html css 和js说明 ##1.什么是html? HTML(HyperText MarkUp ...

  5. Linux 下EXT2文件系统 —— 如何将蚂蚁和大象优雅的装进冰箱里

    这一阵子真是偷懒,无时无刻不和自己身体中的懒癌做斗争.最终我还是被打败了,星期天两天几乎都是荒废过去的,在空闲的时候实际上我内心也是有点焦虑的,不知道去怎么度过这时间.学习吧又不想学习,看电视娱乐吧也 ...

  6. centos6 install mcrypt

    Download the latest epel-release rpm from http://dl.fedoraproject.org/pub/epel/6/x86_64/ Install epe ...

  7. 通过jquery的serializearray处理表单数据成json格式,并提交到后台处理

    var params = $("#myform").serializeArray(); var values = {}; for (var item in params) { va ...

  8. Fedora 23 忘记root密码

    方法:进入单用户模式改密码 进入grub后,按e进入编辑模式.找到以“linux"开头的那一行,在末尾加” rw init=/bin/bash".ctrl-x启动 (grub2用c ...

  9. 前端MVC框架、类库、UI框架选择

    CSS预处理器sass(基于Ruby服务端版)less(客户端版:基于js; 服务端版:基于nodejs) 前端UI框架JqueryMiniUI: http://www.miniui.com/(适用于 ...

  10. 学习MySQL之数据库操作(一)

    所有代码,均为自学时用到的测试与注释,知识细节或知识点不会面面俱到,亦不会有任何讲解,只做为自己学习复习用. ##数据库操作 ##创建数据库 myTest ,并将数据库字符集设为GBK CREATE ...