特性路由
路由系统执行的流程
路由系统的执行流程如下:
- ASP.NET 5监听到一个HTTP请求。然后Routing Middleware就会尝试将route集合中的route匹配该请求。
- 一旦成功匹配一个请求,就找出该route对应的handler。
- 调用该handler上的RouteAsync方法(因为所有的handler都要实现该接口方法)。
- RoutingContext有一个IsHandled标记,如果该标记设置为true,则意味着该请求已经被这个handler成功处理了;如果设置为false,则意味着该handler无法处理该请求,系统会再为此匹配一个route。
和之前的Routing系统有点不同的是,老版的Routing系统一旦成功匹配一个路由,就将其交由其对应的Handler,不管对应的Handler能不能处理该请求,所以就会出现route匹配成功了,但是找不到对应的action,此时就会出现404错误,
而新版对此作出了上述第4步骤的改进(重新将控制权交回给Routing系统,进行重新匹配),看起来还是非常不错的。
Route参数和约束条件的改进
路由服务
路由服务是在 Program.cs 中使用 builder.Services.AddRouting()注册的,
只是默认在 builder 之前已经注册过了,无需我们再次注册。
AddRouting()方法必须在 UseRouting()方法之前运行,它是路由的基础服务。
MapControllerRoute 用于常规路由
MapDefautControllerRoute 用于常规路由 这是上面的内容,但它简写了我上面显示的默认模式的配置。
MapControllers 属性路由 【特性路由】 最常用于 restfull api 或者webapi,
UseMvc 不能跟终结点路由一起使用 支持多路由 支持特性路由
//不启用终结点
builder.services.AddMvc(options => options.EnableEndpointRouting = false);
app.UseMvc(routes =>
{
routes.MapRoute(
name: “default”,
template: “{controller=Home}/{action=Index}/{id?}”);
routes.MapRoute(
name: “defaultXX”,
template: “Test/{controller=xxx}/{action=Index}/{id?}”);
});
UseMvcWithDedaultRoute 是app.UseMvc 的默认值 简写
使用名为“default”的默认路由和以下模板将 MVC 添加到 IApplicationBuilder
请求执行管道:“{controller=Home}/{action=Index}/{id?}”。
UseRouting UseEndpoints 终结点路由 支持多路由
UseRouting() 方法用于配置请求路由。
UseEndpoints() 方法用于定义请求的服务端点。
》》》配置终结点委托
MapGet
MapPost
MapPut
MapDelete
MapControllerRoute
MapHealthChecks
其他类似“MapXXX”的方法
总结
路由一共2种 UseEndpoints 和 UseMvc 不能同时使用
资料
自定义特性路由
比如HttpGet 继承 HttpMethodAttribute
public class MyApiControllerAttribute:Attribute,IRouteTemplateProvider
{
public string Template => "api/[controller]";
public int?Order {get;set}
public string Name {get;set;}
}
上面例子中,当 [MyApiController] 特性被应用,会自动设置 Template 为 “api/[controller]”。
IActionConstraint 路由约束
实现IActionConstraint最简单的方法是创建派生自 System.Attribute 的类,并将其置于操作和控制器上。
MVC 将自动发现任何应用属性IActionConstraint的操作和控制器
//定义ActionConstraint属性约束
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["languagecode"].ToString(),
_countryCode,
StringComparison.OrdinalIgnoreCase);
}
}
//应用路由的action约束,并且路由中id值为en-US
[CountrySpecific("en-US")]
public IActionResult Privacy(string countryCode)
{
return View();
}
//在浏览器测试时:如果输入http://localhost:30081/home/Privacy/zh-cn,则网页显示404。
//如果输入http://localhost:30081/home/Privacy/en-US 则符合约束,网页显示正常。
//路由是
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{languagecode}");
});
》》》》函数区域
...
app.UseMvc(routes =>
{
routes.MapRoute(name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}");
});
》》》区域寻找寻找视图路径
services.Configure<RazorViewEngineOptions>(options =>
{
options.AreaViewLocationFormats.Clear();
options.AreaViewLocationFormats.Add("/Categories/{2}/Views/{1}/{0}.cshtml");
options.AreaViewLocationFormats.Add("/Categories/{2}/Views/Shared/{0}.cshtml");
options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
});