什么是路由
问题 | 答案 |
路由是什么? | 路由系统负责处理传入的请求并选择控制器和操作方法来处理它们。 路由系统还用于在视图中生成路由,称为传出的URL |
路由有什么用? | 路由系统能够灵活地处理请求,面不是将URL与Visual Studio项目中的类结构关取到一起 |
如何使用路由? | URL与控制器和操作方法之间的映射定义在Statup.cs文件中,也可通过将 Route 性应用控制器来实现 |
有什么缺点或限制吗? | 复杂应用程序的路由配置可能会变得难以管理 |
有其他代替方式吗? | 没有,路由系统是ASP.NET Core的组成部分 |
URL模式
网址可以细分为片段。这些是 URL的组成部分,不包括由/字符分隔的主机名和查询字符串。
第一个片段包含单词Admin,第二个片段包含单词 Index
第一个片段与控制器有关,而第二个片段涉及操作。
以下是与示例URL匹配的网址格式:
{controller}/{action}
创建和注册路由
在Startup文件的Configure方法中创建与注册路由
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; }
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { //基本路由 //https://localhost:44352/Home/Index endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action}"); }); } } |
控制器
我们使用到的控制器有:
控制器 | 方法(有一个参数或无参数) |
AdminController | Index |
CustomerController | Index 和 List |
HomeController | Index 和 CustomVariable |
定义默认值路由
//定义默认值路由 //方法一 //基本路由 //https://localhost:44352/Home endpoints.MapControllerRoute( name: "", pattern: "{controller}/{action}", defaults: new { action = "Index" });
//方法二 //https://localhost:44352/ endpoints.MapControllerRoute( name: "", pattern: "{controller=Home}/{action}", defaults: new { action = "Index" }); |
方法一中告诉我们可以在defaults属性中定义默认的路由
方法二告诉我们可以在定义路由模式时定义路由,并且可以混用defaults
静态URL片段
告诉我们并非所有片段必须是变量 https://localhost:44352/Public/Home/Index
//使用静态片段 endpoints.MapControllerRoute( name: "", pattern: "Public/{controller}/{action}"); |
隐藏控制器与Action路由
想象:我们原本使用Shop控制器的,后来被Home取代了,如何不改变路由的情况下修改路由设置?
解决方案: https://localhost:44352/Shop/Index
//更换控制器但不改变路由 //这里是Admin控制器取代了Shop控制器 endpoints.MapControllerRoute( name: "", pattern: "Shop/{action}", defaults: new { controller = "Admin" }); |
带参数的路由配置
带参数的路由,参数默认值是"DefaultId" https://localhost:44352/
//自定义URL参数变量 endpoints.MapControllerRoute( name: "MyRoute", pattern: "{controller=Home}/{action=Index}/{id=DefaultId}"); |
可选带参数的路由配置 https://localhost:44352/home/CustomVariable
//自定义URL可选参数变量 endpoints.MapControllerRoute( name: "MyRoute", pattern: "{controller=Home}/{action=Index}/{id?}"); |
定义可变长度路由:没什么用 https://localhost:44352/Customer/List/MyId/fda/2223d
endpoints.MapControllerRoute( name: "", pattern: "{controller=Home}/{action=Index}/{id?}/{*abc}"); |
控制器中使用路由参数的两种方法
方法一,使用参数形式
public IActionResult Index(string id) { Result r = new Result { Controller = nameof(HomeController), Action = nameof(Index) }; var id = id ?? "<没有值>"; return View(id); } |
方法二,使用RouteData.Values
public IActionResult Index() { var id = RouteData.Values["Id"]; return View(id); } |
路由约束
查看有什么约束
命名空间:Microsoft.AspNetCore.Routing.Constraints
int 约束路由:只能是int值 https://localhost:44352/Home/Index/23
constraints:英文翻译(约束)
endpoints.MapControllerRoute( name: "", pattern: "{controller}/{action}/{id:int?}", defaults: new { controller = "Home", action = "Index" constraints: new { id = new IntRouteConstraint() }); |
int约束路由:只能是Int值。另一种形式
endpoints.MapControllerRoute( name: "", pattern: "{controller=Home}/{action=Index}/{id:int?}"); |
正则表达式约束路由
约束匹配H开头的控制器 https://localhost:44352/Home/Index/827
endpoints.MapControllerRoute( name: "", pattern: "{controller:regex(^H.*$)=Home}/{action=Index}/{id?}"); |
约束以H开头的控制器,并且Action方法是Index或者About https://localhost:44352/Home/Index/827
endpoints.MapControllerRoute( name: "", pattern: "{controller:regex(^H.*$)=Home}/{action:regex(^Index$| ^About$)=Index}/{id?}"); |
范围约束
id参数可选,如果有值只能是在10到20之间(包括10和20) https://localhost:44352/Home/Index/20
endpoints.MapControllerRoute( name: "", pattern: "{controller}/{action}/{id:range(10,20)}", defaults: new { controller = "Home", action = "Index" }); |
组合约束
id值可选,id存在值则必须全是字母并且字母长度不能低于6 https://localhost:44352/home/index/fasdfa
endpoints.MapControllerRoute( name: "", pattern: "{controller=Home}/{action=Index}/{id:alpha:minlength(6)?}"); |
另一种形式
endpoints.MapControllerRoute( name: "", pattern: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }, constraints: new { id = new CompositeRouteConstraint( new IRouteConstraint[] { new AlphaRouteConstraint(), new MinLengthRouteConstraint(6) }) }); |
使用自定义路由约束
你可以在 .net 中使用自定义路由约束的情况有:
- 当你想要对路由参数进行更复杂或特定的验证时,例如匹配枚举值,正则表达式,或自定义逻辑。
- 当你想要扩展框架提供的内置路由约束时,例如 int, bool, datetime 等。
- 当你想要实现 IRouteConstraint 接口并重写 Match 方法时,该方法返回 true 或 false 来表示是否满足约束条件。
创建一个类WeekDayConstraint实现IRouteConstraint接口
public class WeekDayConstraint : IRouteConstraint { private static string[] Days = new[] { "周一", "周二", "周三", "周四", "周五", "周六", "周日" }; public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { return Days.Contains(values[routeKey]?.ToString()); } } |
在Startup文件的ConfigureServices方法注册服务
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.Configure<RouteOptions>(options => { options.ConstraintMap.Add("weekday", typeof(WeekDayConstraint)); }); } |
使用自定义路由约束 https://localhost:44352/Home/Index/周一
endpoints.MapControllerRoute( name: "", pattern: "{controller=Home}/{action=Index}/{id:weekday?}"); |
使用自定义路由约束,不注册服务
如果不想在Startup文件的ConfigureServices方法注册服务
endpoints.MapControllerRoute( name: "", pattern: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }, constraints: new { id = new WeekDayConstraint() }); |
特性路由
特性路由在控制器中操作
但也需要有一个路由,不然无法找到Action方法
endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action}"); |
控制器操作
方式一 只需输入字符串内容:
https://localhost:44352/myroute
[Route("myroute")] public IActionResult Index() { return View(); } |
方式二 使用时必须指定控制器名称:
https://localhost:44352/Customer/MyAction
[Route("[controller]/MyAction")] public IActionResult Index() { return View(); } |
方式三: 在类中使用特性 复杂路由 :
https://localhost:44352/app/Customer/actions/Index/周二
[Route("app/[controller]/actions/[action]/{id:weekday?}")] public class CustomerController : Controller { public IActionResult Index() { return View(); } } |