[译]ASP.NET Core 2.0 路由引擎之网址生成

问题

如何在ASP.NET Core 2.0中由路由引擎来生成网址?

答案

新建一个空项目,修改Startup.cs文件,添加MVC服务和中间件:

1public void ConfigureServices(IServiceCollection services) 2{ 3 services.AddMvc(); 4} 5 6public void Configure(IApplicationBuilder app, IHostingEnvironment env) 7{ 8 if (env.IsDevelopment()) 9 { 10 app.UseDeveloperExceptionPage(); 11 } 12 13 app.UseMvc(routes => 14 { 15 routes.MapRoute( 16 name: "goto_one", 17 template: "one", 18 defaults: new { controller = "Home", action = "PageOne" }); 19 20 routes.MapRoute( 21 name: "goto_two", 22 template: "two/{id?}", 23 defaults: new { controller = "Home", action = "PageTwo" }); 24 25 routes.MapRoute( 26 name: "default", 27 template: "{controller=Home}/{action=Index}/{id?}"); 28 }); 29} 30

添加一个MobileController控制器类:

1public class MobileController : Controller 2{ 3 public IActionResult Index() 4 { 5 var url = Url.Action("Index"); // /mobile 6 return Content($"Mobile/Index (Url: {url})"); 7 } 8 9 public IActionResult PageOne() 10 { 11 var url = Url.Action("PageOne"); // /mobile/PageOne 12 return Content($"Mobile/One (Url: {url})"); 13 } 14 15 [HttpGet] 16 public IActionResult PageTwo() 17 { 18 var url = Url.Action("PageTwo"); // /mobile/PageTwo OR /mobile/PageTwo/1? 19 return Content($"(GET) Mobile/Two (Url: {url})"); 20 } 21 22 [HttpPost] 23 public IActionResult PageTwo(int id) 24 { 25 var url = Url.Action("PageTwo"); // /mobile/PageTwo/1 26 return Content($"(POST) Mobile/Two: {id} (Url: {url})"); 27 } 28 29 public IActionResult PageThree() 30 { 31 var url = Url.RouteUrl("goto_two", new { id = 5 }); // /two/5 32 return Content($"Mobile/Three (Url: {url})"); 33 } 34 35 public IActionResult PageFour() 36 { 37 var url = Url.RouteUrl("goto_two", new { q = 5 }); // /two?q=5 38 return Content($"Mobile/Four (Url: {url})"); 39 } 40 41 public IActionResult PageFive() 42 { 43 return RedirectToAction("PageSix"); 44 } 45 46 public IActionResult PageSix() 47 { 48 return Content("Mobile/Six (Mobile/Five will also come here)"); 49 } 50} 51

讨论

我们可以使用MVC的路由机制来生成网址,而无需在应用程序中硬编码网址。MVC有这么做的所有信息,来自于我们设置路由映射所提供的模板。

MVC提供了IUrlHelper接口来提供生成网址的功能。这是通过在控制器基类,视图和试图组件公开Url属性来实现的。

IUrlHelper接口提供两个关键的方法来生成网址:

  1. Action:通过提供控制器,方法和路由参数值来生成网址。
  2. RouteUrl: 通过提供路由映射名称和路由参数来生成网址。

如果调用上述方法时未提供控制器和路由参数,那么MVC会从当前请求或者方法参数中获取(即是从当前上下文的环境变量中获取)。下面的方法存在于MobileController控制器中:

1public IActionResult PageTwo(int id) 2{ 3 var url = Url.Action("PageTwo"); // /mobile/PageTwo/1 4 return Content($"(POST) Mobile/Two: {id} (Url: {url})"); 5}   6

路由参数可以作为匿名对象来提供:

1public IActionResult PageThree() 2{ 3 var url = Url.RouteUrl("goto_two", new { id = 5 }); // /two/5 4 return Content($"Mobile/Three (Url: {url})"); 5} 6

如果MVC无法将这些值映射到地址标记,那么这些参数会作为网址的查询字符串拼接起来:

1public IActionResult PageFour() 2{ 3 var url = Url.RouteUrl("goto_two", new { id=5, key1 = "value1" }); // /two/5?key1=value1 4 return Content($"Mobile/Four (Url: {url})"); 5} 6

ControlBase类上有一个很方便的方法RedirectToAction,用来将用户请求重定向到某个控制器方法中,这一过程是在客户端完成的:

1public IActionResult PageFive() 2{ 3 return RedirectToAction("PageSix"); 4} 5 6public IActionResult PageSix() 7{ 8 return Content("Mobile/Six (Mobile/Five will also come here)"); 9} 10

  

为了将IUrlHeper作为依赖项注入需要的类中,我们需要首先在ConfigureServices中配置相应的服务:

1public void ConfigureServices(IServiceCollection services) 2{ 3 services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); 4 services.AddScoped<IUrlHelper>(factory => 5 { 6 var actionContext = factory.GetService<IActionContextAccessor>().ActionContext; 7 return new UrlHelper(actionContext); 8 }); 9 10 services.AddMvc(); 11}   12

注:大部分情况下我们无需通过注入来使用IUrlHelper,因为控制器,视图中都已经公开了Url属性供我们使用。

 

源代码下载

 

原文:https://tahirnaushad.com/2017/08/20/asp-net-core-mvc-routing/

代码交流 2021