频道栏目
首页 > 网络 > 路由器 > 正文
asp.net mvc5 特性路由
2017-09-06 09:41:16      个评论    来源:z767327552的专栏  
收藏   我要投稿

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中默认的路由约束有:

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,这种约束可以复合使用。如:

    // 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方法来生成一个链接:

    Main menu

区域

[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 }
        );
    }
点击复制链接 与好友分享!回本站首页
上一篇:腾讯2017校招开发工程师:设有2条路由21.1.193.0/24和21.1.194.0/24,如果进行路由汇聚
下一篇:无线路由器登录密码忘了怎么办 这里教你轻松解决
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训

版权所有: 红黑联盟--致力于做实用的IT技术学习网站