目录
1.设置路由中间件2.常规路由3.多路由1.回退2.行动歧义3.路由名称4.路由特性5.组合路由6.特性路由的顺序7.路由模板中的标记替换( [controller] , [action] , [area])8.使用IRouteTemplateProvider自定义路由特性9.使用应用程序模型来自定义特性路由10.URL生成11.通过操作名生成URL12.通过路由名生成URL13.在操作结果中生成URL14.专用常规路由的特殊情况15.区域16.IActionConstraintASP.NET Core MVC 路由是建立在ASP.NET Core 路由的,一项强大的URL映射组件,它可以构建具有理解和搜索网址的应用程序。这使得我们可以自定义应用程序的URL命名形式,使得它在搜索引擎优化(SEO)和链接生成中运行良好,而不用关心Web服务器上的文件是怎么组织的。我们可以方便的使用路由模板语法定义路由,路由模板语法支持路由值约束,默认值和可选值。
基于约束的路由允许全局定义应用支持的URL格式,以及这些格式是怎样各自在给定的控制器中映射到指定的操作方法(Action)。当接受到一个请求时,路由引擎解析URL并将其匹配至一个定义URL格式,然后调用相关的控制器操作方法。
routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}");特性路由(Attribute Routing) 允许以在控制器和方法使用添加特性的方式指定路由信息来定义应用程序的路由。这意味着路由定义紧邻它们所关联的控制器和方法。
ASP.NET Core MVC 使用路由中间件来匹配传入请求的URL,并将它们映射到操作方法。路由在启动代码或属性中定义,它描述了网址路径应如何与操作方法匹配,还用于响应中生成链接并发送。
1.设置路由中间件
创建一个ASP.NET Core Web应用程序,在Startup类的Configure方法中有:
app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });在对UseMvc的调用过程中,MapRoute用于创建单个路由,即默认路由。大多数MVC应用程序都使用与默认路由模板类似的路由。
路由模板{controller=Home}/{action=Index}/{id?} 可以匹配类似 Blog/Details/5 的URL路径,并且提取路由值 {controller=Blog,action=Details,id=5}。MVC将尝试查找名为BlogController的控制器,并运行操作方法。
{controller=Home}将Home定义为默认控制器
{action=Index}将Index定义为默认操作
{id?}将id定义为可选
默认路径参数和可选路径参数可以不出现在需要匹配的URL路径中。
使用{controller=Home}/{action=Index}/{id?}模板,可以对以下URL路径都执行HomeController.Index:
/Home/Index/7
/Home/Index
/Home
/
有个简单方法 app.UseMvcWithDefaultRoute() 可以替换掉上面的方法。
UseMvc 和 UseMvcWithDefaultRoute 都是将RouteMiddleware的实例添加到中间件管道。MVC不直接与中间件交互,而是使用路由来处理请求。MVC通过MvcRouteHandler的实例链接到路由。下面的代码与UseMvc类似:
var route = new RouteBuilder(app); //添加连接到MVC,通过调用MapRoute来回调 route.DefaultHandler = new MvcRouteHandler(...); //执行回调以注册路由 route.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"); //创建路由集合并添加至中间件 app.UseRouter(route.Build());UseMvc 不直接定义任何路由,它为属性路由的路由集合添加一个占位符。重载UseMvc 使得我们可以添加自己的路由,并且还支持属性路由。UseMvc 及其所有变体为属性路由添加了占位符,这使得属性路由始终可用。UseMvcWithDefaultRoute定义默认路由并且支持属性路由。
2.常规路由
routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}"); 这是一个常规路由,因为它建立了一个约定的URL路径:
第一路径段映射到控制器名称第二路径映射到操作名称第三区段是可选id,用于映射到模型实体使用default路由,URL 路径 /Blog/Index 将映射到BlogController.Index 操作。该映射是基于控制器和操作名称,而不是基于命名空间,源文件位置等。
使用常规路由的默认路由可以快速构建应用程序,而无需定义每一个操作的路由。对于CRUD 操作风格的应用程序,整个控制器的URL具有一致性。
3.多路由
可以在UseMvc 里面通过添加MapRoute 来添加多个路由。这样可以定义多个约定,或添加专用于特定操作的常规路由:
app.UseMvc(routes => { routes.MapRouttion 的当前值,并且生成路由到当前操作的URL路径。路由尝试使用环境值中的值来填充信息,同时我们也可以指定路由参数:
public class HomeController : Controller { public IActionResult Index() { //生成/Blog/Edit/1 var url = Url.Action("Edit", "Blog",new { id=1}); //生成/Blog/Edit/1?color=red var url1 = Url.Action("Edit", "Blog", new { id = 1 ,color="red"}); return View(); } }如果像创建一个绝对URL,可以使用一个接受protocol的重载: Url.Action("Edit", "Blog",new { id=1},protocol:Request.Scheme);
12.通过路由名生成URL
IUrlHelper也提供了 Url.RouteUrl 的系列方法,最常见的是指定一个路由名来使用具体的路由生成URL,通常没有指定控制器名或操作名:
public class HomeController : Controller { public IActionResult Index() { //生成customer/to/url var url = Url.RouteUrl("AboutRoute"); return View(); } [HttpGet("customer/to/url",Name = "AboutRoute")] public IActionResult About() { ViewData["Message"] = "Your application description page."; return View(); } }在HTML 中生成的URLHtmlHelper,提供了 HtmlHelper 方法 Html.BeginForm 和 Html.ActionLink 来分别生成<form>和<a>元素。这些方法使用Url.Action方法来生成一个URL,并且它们接受类似的参数。Url.RouteLink ,它们有类似的功能。TagHelper通过form和<a> TagHelper生成URL。这些都使用了IUrlHelper 作为它们的实现。在内部视图中,IUrlHelper 通过Url 属性生成任何不包含上述的特定URL。
13.在操作结果中生成URL
在控制器中常见的一个用法是生成一个URL作为操作结果的一部分。Controller和ControllerBase 基类为引用其他操作的操作结果提供了简单方法。一个典型的方法:
public class HomeController : Controller { public IActionResult Index() { //生成customer/to/url var url = Url.RouteUrl("AboutRoute"); return Redirect(url); //或者 //return RedirectToAction("Contact"); } [HttpGet("customer/to/url",Name = "AboutRoute")] public IActionResult About() { ViewData["Message"] = "Your application description page."; return View(); } public IActionResult Contact() { ViewData["Message"] = "Your contact page."; return View(); } }RedirectToAction方法有多个重载可以使用。
14.专用常规路由的特殊情况
有一种特殊的路由被称为专用常规路由,下面被命名为blog的路由就是:
app.UseMvc(routes => { routes.MapRoute("blog", "blog/{*article}", defaults: new { Controller = "Blog", Action = "Index" }); routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });Url.Action("Index", "Home") 会使用默认路由生成URL。
专用常规路由是依靠默认路由的一个特殊行为,没有相应的路由参数,以防止路由生成URL“太贪婪”。当路由执行URL生成时,提供的值必须与默认值匹配:否则使用blog的URL生成失败,因为值 {controller=Home,action=Index}不匹配{controller=Blog,action=Index}。然后路由回退尝试default,并成功。
15.区域
Areas 是一种MVC功能,用来将相关功能组织为一个组,作为单独的路由命名空间(用于控制器操作)和文件夹结构(用于视图)。使用区域允许应用程序拥有多个相同名称的控制器——只要它们具有不同的区域。使用区域通过向控制器和操作添加另一个路由参数,区域可创建用于路由目的的层次结构。
使用默认常规路由配置MVC,命名一个OMS区域的路由:
app.UseMvc(routes => { routes.MapAreaRoute("oms", "OMS", "OManage/{controller}/{action}/{id?}", defaults: new { Controller = "Order", Action = "Index" }); routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });namespace Blog.Areas.OMS.Controllers{ [Area("OMS")] public class OrderController : Controller { // GET: Order public ActionResult Index() { return View(); }}当URL为 /OManage/Order/Edit 时,会匹配路由值 {area = OMS,controller = Order , action = Edit}。area路由值是通过area默认值产生的。使用MapRoute方法也可以实现:
routes.MapRoute("oms", "OManage/{controller}/{action}/{id?}", defaults:new {area="OMS" },constraints:new { area = "OMS" });MapAreaRoute创建一个路由,同时使用默认路由和area 约束,约束使用提供的区域名 OMS。默认值保证路由总是处理 {area = OMS},约束要求值{area = OMS} 来进行URL生成。
常规路由是顺序依赖。一般区域路由放置在前面,因为区域路由更具体。
AreaAttribute表示控制器属于一个区域的一部分,即这个控制器是在 OMS 区域。控制器不带[Area] 特性则不属于任何区域。
当在区域内执行操作时,区域的路由值将作为环境值以用于URL生成,这意味着,在默认情况下,区域对URL生成具有黏性:
namespace Blog.Areas.OMS.Controllers{ [Area("OMS")] public class OrderController : Controller { // GET: Order public ActionResult Index() { //生成/OManage/Home/Create var url = Url.Action("Create","Home"); //生成/Home/Create var url1 = Url.Action("Create", "Home",new { area=""}); return View(); } }}16.IActionConstraint
通常应用程序不需要自定义 IActionConstraint,[HttpGet] 特性以及类似的特性实现 IActionConstraint 接口,以限制方法的执行。
当两个操作一模一样,其中一个操作使用 IActionConstraint,总是认为比没有使用的操作更好,因为它被视为更加具体,并且两个操作都可以在匹配是被选中。(没有使用的操作会匹配任何HTTP谓词)
概念上,IActionConstraint 是重载的一种形式,但不是使用相同名称的重载,它是匹配相同URL操作的重载。特性路由也使用 IActionConstraint ,并且可以导致不同控制器的操作都被视为候选操作。
实现 IActionConstraint 最简单的方式是创建一个类派生自 System.Attribute ,并且将它放置到操作和控制器上。MVC会自动发现任何作为特性被应用的 IActionConstraint。你可以使用程序模型来应用约束,可能是最灵活的方法,因为它允许对它们如何被应用进行元编程。
一个例子,一个约束选择一个基于来自路由数据的 country code 操作:
public class CountrySpecificAttribute:Attribute,IActionConstraint { private readonly string _countryCode; public CountrySpecificAttribute(string countryCode) { _countryCode = countryCode; } public int Order { get { return 0; } } public bool Accept(ActionConstraintContext context) { return string.Equals( context.RouteContext.RouteData.Values["country"].ToString(), _countryCode,StringComparison.OrdinalIgnoreCase); } }Accept 方法返回true,表示当country路由值匹配时操作时匹配的。这个和 RouteValueAttribute 不同,因为它允许回退到一个非特性操作。这个例子展示了如果定义一个 en-US 操作,然后国家代码是 fr-FR,则会回退到一个更通用的控制器,这个控制器没有应用 [CountrySpecific(...)] 。
Order属性和 [HttpGet] 特性中的Order属性一样,用来决定运行顺序。
到此这篇关于ASP.NET Core MVC路由的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。








