2 根据定义的路由生成URL链接
// 堆代码 duidaima.com app.UseRouting(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");我们配置app.UseRouting() 路由中间件,接着为应用程序添加一个default路由app.MapControllerRoute()方法,这个路由根据url指定的模板映射到终结点,这意味着当应用程序接收url匹配 {controller=Home}/{action=Index}/{id?} 会调用Home控制器中的Index方法。
1 / 2 /Home 3 /Home/Index 4 /Products/Details 5 /Products/Details/3ASP.NET Core 应用程序中有一个HomeController.cs,该控制器里面包含一个Index方法,代码如下:
using AspNetCore.URLRouting.Models; using Microsoft.AspNetCore.Mvc; using System.Diagnostics; namespace AspNetCore.URLRouting.Controllers { public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult Index() { return View(); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } } }现在,修改Index.cshtml 视图代码(Views->Home)文件夹内:
@{ Layout = null; } @{ ViewData["Title"] = "Routing"; } <h1>'Home' Controller, 'Index' View</h1>运行应程序,你将看到Index视图显示到浏览器,图片如下:
app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");2.1 .NET Core 5.0 和 ASP.NET Core 3.0
app.UseEndpoints(endpoints => { // Default route endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); });花括号{}内部代表一个段,默认路由有3个段:
app.MapControllerRoute( name: "default", pattern: "{controller}/{action}");运行应用程序,你将获取404错误,因为路由系统不能映射到任何Controller的URL,如下图所示:
段 |
URL |
映射到 |
0 |
/ |
无法匹配 |
1 |
/Home |
无法匹配 |
2 |
/Home/Index |
controller=Home action=Index |
2 |
/Home/Show/4 |
无法匹配 |
3 |
/Home/Show/4 |
无法匹配 |
app.MapControllerRoute( name: "news1", pattern: "News/{controller=Home}/{action=Index}");路由包含一个静态文本-News,运行应用程序并在浏览器中打开如下地址https://localhost:7134/News,你会发现Home控制器的Index方法被调用。让我们理解发生了什么,路由匹配3个段,第一个是News一个静态文本,第二个和第三个段Controller和Action是可选的,如果省略,默认会访问Home控制器的Index方法。
app.MapControllerRoute( name: "news2", pattern: "News{controller}/{action}");这里我们添加了静态文本News结合Controller段的值,现在运行应用程序并且进入https://localhost:7134/NewsHome/Index,你会发现Home控制器中的Index方法被调用
app.MapControllerRoute( name: "shop", pattern: "Shopping/{action}", defaults: new { controller = "Home" });路由匹配两个段,第一个段是Shopping,第二个段是action方法,URL模板没有包含Controller段,因此这时会使用默认值,默认参数提供了一个HomeController的值
app.MapControllerRoute( name: "old", pattern: "Shopping/Old", defaults: new { controller = "Home", action = "Index" });https://localhost:7134/Shopping/Old 会映射到Home中的 Index方法,如下图所示:
//堆代码 duidaima.com app.MapControllerRoute( name: "old", pattern: "Shopping/Old", defaults: new { controller = "Home", action = "Index" }); app.MapControllerRoute( name: "shop", pattern: "Shopping/{action}", defaults: new { controller = "Home" }); 在HomeController中添加一个新的Action方法Old, 代码如下: public IActionResult Old() { return View(); }下一步,在Views->Home文件夹添加Old视图,内容如下:
@{ Layout = null; } <h1>'Home' Controller, 'Old' View</h1>运行应用程序并打开https://localhost:7134/Shopping/Old 在浏览器中,这次你将发现HomeController中的Index方法被调用,看如下图片:
app.MapControllerRoute( name: "shop", pattern: "Shopping/{action}", defaults: new { controller = "Home" }); app.MapControllerRoute( name: "old", pattern: "Shopping/Old", defaults: new { controller = "Home", action = "Index" });我们再次请求https://localhost:7134/Shopping/Old地址时,这次你会发现Home控制器中的Old方法被调用,如下图所示:
app.MapControllerRoute( name: "MyRoute", pattern: "{controller=Home}/{action=Index}/{id}");在这个路由中我添加了自定义的段叫id,接下来在HomeController中添加一个新的Action叫Check:
public IActionResult Check() { ViewBag.ValueofId = RouteData.Values["id"]; return View(); }这个action方法使用RouteData.Values属性获取路由模板中客户自定义变量id的值,并且将值存储在ViewBag变量,创建一个check 视图在Home->Check文件夹下,Check视图的代码如下:
@{ Layout = null; } <h1>'Home' Controller, 'Check' View</h1> <h2>Id value is: @ViewBag.ValueofId</h2>运行程序进入https://localhost:7134/Home/Check/cSharp 。
app.MapControllerRoute( name: "MyRoute", pattern: "{controller=Home}/{action=Index}/{id}");为了能获取url中id的值,我们在action方法中添加一个id参数,因此我们在action方法中添加一个id的参数:
public IActionResult Check(int id) { ViewBag.ValueofId = id; return View(); }我们注意到在方法内部,我们仅仅将id变量的值赋值给ViewBag变,访问https://localhost:7134/Home/Check/100 。
public IActionResult Check(string id) { ViewBag.ValueofId = id; return View(); }
当请求URL-https://localhost:7134/Home/Check/hello 或者https://localhost:7134/Home/Check/100,框架会自动将客户自定义id变量的值(hello 和100)转化成string 。
app.MapControllerRoute( name: "MyRoute1", pattern: "{controller=Home}/{action=Index}/{id?}");当你没有给可选的参数提供值时,路由也会被匹配成功,只不过id值会被设置成null 。
public IActionResult Check() { ViewBag.ValueofId = RouteData.Values["id"]; return View(); }运行程序,访问URL-https://localhost:7134/Home/Check
public IActionResult Check(string id) { ViewBag.ValueofId = id ?? "Null Value"; return View(); }将参数id类型修改为string类型,现在代码ViewBag.ValueofId = id ?? "Null Value" 表示如果id的值为null,会将Null Value的值赋值给ViewBag变量,否则,将id的值赋值给ViewBag变量。运行程序并且访问-https://localhost:7134/Home/Check 地址,你会发现Null Value显示在浏览器:
app.MapControllerRoute( name: "MyRoute2", pattern: "{controller=Home}/{action=Index}/{id?}/{idtwo?}");如果第5个段出现,你不得不添加另外一个新的路由来匹配5段,这很乏味而且会有大量代码重复,可以在路由中使用*catchall ,在url段的变量中它将扮演通配符的角色.我们将路由的第四段修改为 {*catchall} , 它将是:
app.MapControllerRoute( name: "MyRoute2", pattern: "{controller=Home}/{action=Index}/{id?}/{*catchall}");我们已经添加了{*catchall}作为在路由中作为第四段,前3段分别映射到controller, action & id 变量,如果URL包含的段大于3,catchall变量将捕获所有的段,即:从第4段直到最后
段 |
URL |
映射 |
0 |
/ |
controller = Homeaction = Index id = Null |
1 |
/Home |
controller = Homeaction = Index id = Null |
2 |
/Home/CatchallTest |
controller = Homeaction = CatchallTest Id = Null |
3 |
/Home/CatchallTest/Hello |
controller = Homeaction = catchallTest id = Hello |
4 |
/Home/CatchallTest/Hello/How | controller = Homeaction = catchallTest id = Hello catchall = How |
5 |
/Home/CatchallTest/Hello/How/Are | controller = Homeaction = catchallTest id = Hello catchall = How/Are |
6 |
/Home/CatchallTest/Hello/How/Are/U | controller = Homeaction = catchallTest id = Hello catchall = How/Are/You |
public IActionResult CatchallTest(string id, string catchall) { ViewBag.ValueofId = id; ViewBag.ValueofCatchall = catchall; return View(); }我们在action方法中添加了一个新的参数名字为cacthall,这个参数的值是URL中除了前3段剩余所有段的值,我们将cacthall的值存储到ViewBag的ValueofCatchall变量中。
@{ Layout = null; } <h1>'Home' Controller, 'CatchallTest' View</h1> <h2>Id value is: @ViewBag.ValueofId</h2> <h2>Catchall value is: @ViewBag.ValueofCatchall</h2>视图将会显示ViewBag中变量的值,运行程序且进入URL-https://localhost:7134/Home/CatchallTest/Hello/How/Are/U你会发现catchall的值为How/Are/U显示在视图中