asp.net mvc5 特性路由

来源:互联网 发布:php 解析优酷视频地址 编辑:程序博客网 时间:2024/06/08 17:50

asp.net mvc中的路由是如何去匹配URL的呢?
mvc5支持一种新的路由方式,叫做特性路由。顾名思义,特性路由就是利用特性去定义路由。特性路由让你在应用程序中能更好的控制URL。
早期的路由方式,叫做传统路由,现在也是完全支持的。实际上,你可以将两种技术结合在同一个项目当中。
这篇文章将会涵盖asp.net mvc5中特性路由所有的基本用法。


为什么要特性路由?

举个例子,一个电子商务网站会有以下路由:

  • {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文件中进行设置,让它指向正确的控制器和方法,如:

`

routes.MapRoute(    name: “ProductPage”,    url: “{productId}/{productTitle}”,    defaults: new { controller = “Products”, action = “Show” },    constraints: new { productId = “\\d+” });

`
当路由定义的方法都来源于一个控制器中,此时我们可以使用特性路由进行简单化处理,特性路由可更容易的看清URL和action之间的映射。如下设置:

    [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 }        );    }

可选参数和默认值
你可以通过使用?来设置URL可选参数,也可以使用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 都是匹配的一个方法和视图,但前者会列举出所有的书籍,而后者只会列举出特定的书籍。 /books/lang 和 /books/lang/en 都是此理。

路由前缀
在控制器中会使用一样的前缀,例如:

    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) { … }    }

也可利用此符号 (~) 在路由特性中标识省略前缀,如:

    [RoutePrefix(“reviews”)]    public class ReviewsController : Controller    {        // eg.: /spotlight-review        [Route(“~/spotlight-review”)]        public ActionResult ShowSpotlight() { … }        …    }

默认路由
你也可以在控制器上利用[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) { … }    }

路由约束
路由约束 可以让你更严格的去限制这个路由参数是否匹配. 其语法为:{parameter:constraint}. 例子:

    // eg: /users/5    [Route(“users/{id:int}”]    public ActionResult GetUserById(int id) { … }    // eg: users/ken    [Route(“users/{name}”]    public ActionResult GetUserByName(string name) { … }

首先先进入第一个路由,判断其参数id是否为int类型,不是则进入下一个路由进行匹配。
mvc中默认的路由约束有:

ConstraintDescriptionExamplealphaMatches uppercase or lowercase Latin alphabet characters (a-z, A-Z){x:alpha}boolMatches a Boolean value.{x:bool}datetimeMatches a DateTime value.{x:datetime}decimalMatches a decimal value.{x:decimal}doubleMatches a 64-bit floating-point value.{x:double}floatMatches a 32-bit floating-point value.{x:float}guidMatches a GUID value.{x:guid}intMatches a 32-bit integer value.{x:int}lengthMatches a string with the specified length or within a specified range of lengths.{x:length(6)}
{x:length(1,20)}longMatches a 64-bit integer value.{x:long}maxMatches an integer with a maximum value.{x:max(10)}maxlengthMatches a string with a maximum length.{x:maxlength(10)}minMatches an integer with a minimum value.{x:min(10)}minlengthMatches a string with a minimum length.{x:minlength(10)}rangeMatches an integer within a range of values.{x:range(10,50)}regexMatches a regular expression.{x:regex(^\d{3}-\d{3}-\d{4}$)}

有些约束是需要注意的,如Min,这种约束可以复合使用。如:

    // 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);        }    }

路由名
可以为路由指定一个名字,这样就可以方便的生成URL。例如:

    [Route(“menu”, Name = “mainmenu”)]    public ActionResult MainMenu() { … }

可以使用Url.RouteUrl方法来生成一个链接:

    <a href=”@Url.RouteUrl(“mainmenu”)“>Main menu</a>

区域

[RouteArea]利用这个特性可以标识在区域下的控制器。如果使用了此特性,那么区域注册就可以不用了,直接移除AreaRegistration 类。

    [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() { … }    }

在这个控制器中,使用Url.Action会生成这样的URL: /Admin/menu/show-options
如:

    Url.Action(“Options”, “Menu”, new { Area = “Admin” })

假如想将区域设置一个别名,利用AreaPrefix 即可。如:

 [RouteArea(“BackOffice”, AreaPrefix = “back-office”)]

在区域中假如想使用传统路由和特性路由,那么区域中的传统路由需要注册好,避免路由丢失。
如:

    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 }        );    }

原文地址:https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/#why-attribute-routing

阅读全文
0 0
原创粉丝点击