【转】【ASP.NET Core】给路由规则命名有何用处
原文地址:https://www.cnblogs.com/tcjiaan/p/8439178.html
规则模板
我们都知道,在 Startup.Configure 方法中,会以此方式来指定 URL 路径规则。
app.UseMvc(route => { route.MapRoute("main", "{controller=Students}/{action=List}/{sid?}"); route.MapRoute("edit_post", "{controller}-{action}"); });
你可以添加 K 条规则,比如上面的例子,我添加了两条规则。
{controller} 和 {action} 是约定的名称,用来识别 Controller 和 Action ,所以你不要自作聪明乱来。其他参数如果是可选的,可以在后面加个问号,比如 {controller}/{action}/{id?},这表示 id 的值是可选的。上面老周添加的两个规则中,edit_post 那个其实不太规范,URL 中各段最好用 “/” 来分隔,因为 “-” 有时候是不允许用的,比如,id 参数前面就不能用,你不能写成 {controller}-{action}-{id?},要是 id 中包含了字符“-”,咋办呢?而“/”则不同,URL Encode 后不会冒出这个字符来。所以用 / 最好,这里用 - 只是老周故意用来演示而已。
基于 Attribute 指定的 URL 路由
在 Startup.Configure 方法中指定的 URL 路由是作用于整个应用程序的,如果想为个别控制器或个别 Action 指定路由规则,那么可以考虑使用 Attribute 的形式。
attribute 形式的路由规则和应用程序级别的规则相似,只是,在应用级别时,用大括号来包裹参数名(如 {controller}),而在 Attribute 方案中,是用中括号的,它只能用两个值:[controller]、[action]。其他参数也是用大括号。比如,[controlloer]/[action]/[id?] 会报错,你得改为 [controller]/[action]/{id?}。
RouteAttribute 既可以用于 Controller 类型,也可能用于单个 Action 方法上。我举个例子,像这样。
[Route("hello/[controller]/[action]")] public class SomethingController : Controller { [Route("{name?}")] public IActionResult SayHi(string name) { …… } }
在类上应用用的 Attribute 中,可以使用这样的 URL :http://localhost:999/hello/something/sayhi 。而在 SayHi 方法上,又用了 Route Attribute,指定了一个附加参数 name,并且是可选的。于是它可以与类上的 Route attribute 合并,变成:http://localhost:999/hello/something/sayhi/Peter。这时,字符串 Peter 会传给 SayHi 方法的 name 参数,因为,参数的名字与 Route 中的参数名是相同的,都叫 name。如果 SayHi 中的参数名不叫 name,那你得运用一下 FromRouteAttribute 了。就像这样。
[Route("{name?}")] public IActionResult SayHi([FromRoute(Name = "name")]string who) { …… }
如果你希望 URL 中给 name 传入 int 类型的值,你还可以限制它。
[Route("{name:int}")]
其实这些约束条件对应的是 Microsoft.AspNetCore.Routing.Constraints 命名空间下面的类型。

Route Data
Route data 其实就是一个字典,存放的就是 URL 路径规则中参数与值的 key-value 对。这个很简单,我举个例子,你就明白了。
咱们就直接用上面那个例子吧。
[Route("hello/[controller]/[action]")] public class SomethingController : Controller { [Route("{name?}")] public IActionResult SayHi([FromRoute(Name = "name")]string who) { return Json(RouteData.Values); } }
在 SayHi 方法中,咱们把 route data 返回。
运行应用后,输入地址:http://localhost/hello/something/sayhi/Tom,得到的输出如下:

给路由命名
上面的都是 F 话,本小节才是本文的主题。我们回头看看上面老周举过例的那个 route。
app.UseMvc(route => { route.MapRoute("main", "{controller=Students}/{action=List}/{sid?}"); route.MapRoute("edit_post", "{controller}-{action}"); });
每条路由规则都会有自己的 name,为啥要命名?最直接的理由是为了唯一标识每条规则。除了此因素外,我们可以在开发过程中选择使用哪条规则,有了 name,想找出某条规则就好办了,就好比你上学的时候,老师点名,要么点姓名,要么点学号。
基于 Attribute 的路由规则也可以命名的,例如。
[Route("hello/[controller]/[action]", Name = "prv")] //这样就把它命名为 prv 了,你还可以这样写。 [Route("hello/[controller]/[action]", Name = "[controller]_[action]")]
这样也可以用 Controller 和 Action 的名字生成一个唯一的名字,比如 Something_SayHi。但是这种方法太动态了,好像不那么好操控,还是用一个固定的名字好一点。
要在开发的时候选择使用指定的 URL 路由,需要在 Razor 页中添加 Tag Helper,标记帮助类可以扩展 HTML 标记的某些功能。在需要使用 tag helper 的页面,或者统一在 _ViewImports.cshtml 页中加入这些指令。
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
格式是这样的:<类型全路径>, <程序集>
类型写在前面(包括 namespace 名),程序集名写在后面,用逗号分隔。这里用星号(*)是最爽的,它是通配符,表示引入所有 tag helper 类型。这样快捷,一行代码了事。
然后在 HTML 中你这样写。
<form method="post" asp-route="edit_post"> <div class="form-group"> <label asp-for="Name"></label> <input asp-for="Name" class="form-control"/> <span asp-validation-for="Name" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Age"></label> <input asp-for="Age" class="form-control"/> <span asp-validation-for="Age" class="text-danger"></span> </div> <input asp-for="ID"/> <button type="submit" class="btn btn-dark">提交</button> </form>
其他代码你不用看了,只看这一句就够了: asp-route="edit_post"
它的意思就是使用我刚刚定义的那条规则。 route.MapRoute("edit_post", "{controller}-{action}");
所以,在运行后就会生成这样的 HTML。
<form method="post" action="/Students-Editdata"> <div class="form-group"> 此处省略 1650 个字 </form>
因为我定义的规则是 {controller}-{action}的形式,所以,Controller 是 Students,Action 是 Editdata,连起来就是 Students-Editdata。
那么,这里它为什么能识别出 controller 和 action 的值呢,你看看我的代码就知道了。
public class StudentsController : Controller { readonly StudentDBContext m_context; // 接收依赖注入 public StudentsController(StudentDBContext c) { m_context = c; } public IActionResult List() { var q = from s in m_context.Students orderby s.ID select s; return View(q.ToList()); } /***************************************************/ // 以下方法用于编辑页 [HttpGet] public IActionResult Editdata([FromRoute(Name = "sid")] int id) { var q = from s in m_context.Students where id == s.ID select s; Student stu = q.FirstOrDefault(); if(stu == null) { return Content("在地球上找不到此学员。"); } return View(stu); } [HttpPost] public IActionResult Editdata(Student s) { if (ModelState.IsValid == false) { return View(s); } m_context.Students.Update(s); m_context.SaveChanges(); return RedirectToAction(nameof(List)); } }
我定义了 Editdata 方法的重载,一个用于 get 请求,一个用于 post 请求,form 是以 post 方式提交,因此它能自动识别出 controller 和 action 的名字。
那万一,如果不是同名的呢,好办。你用 asp-route-<value> 来指定各个参数的值。比如这样
<form method="post" asp-route="edit_post" asp-route-controller="Demo" asp-route-action="Runwork" asp-route-sid="1">
在 asp-route- 后面直接跟上路由规则参数的名称就可以了。有一点要注意,asp-route 与 asp-controller、asp-action是会冲突的,如果你用了这两个标记,就不能用 asp-route 标记了,当然 asp-route-xxx 是可以用的。

浙公网安备 33010602011771号