asp.net mvc5 特性路由

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

ConstraintDescriptionExample
alphaMatches 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值