用户请求接口路由,应用返回处理结果。应用中如何匹配请求的数据呢?为何能如此精确的找到对应的处理方法?今天就谈谈这个路由。路由负责匹配传入的HTTP请求,将这些请求发送到可以执行的终结点。终结点在应用中进行定义并且在应用启动的时候进行配置,也就是在中间件中进行处理。

路由基础知识

  在项目新建的时候都会自动生成路由相关代码。在Startup.Configure中的中间件管道注册的。主要涉及到的则是UseRoutingUseEndpoints中间件。
    UseRouting向中间件添加路由匹配。此中间件还会查看应用中定义的终结点集。也就是把应用中的路由统统注册到中间件管道,方便请求的时候进行匹配。
    UseEndpoints向中间件添加终结点执行。会运行相关联的委托。简单将就是路由匹配之后的处理事件运行。
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
  例如上面的代码就是HTPP GET 请求并且Url是/的时候需要执行的委托、如果这里的请求不是Get请求或者不是"/",那么没有路由匹配,则会返回404。同时指定匹配模式的还有MapDelete、MapMethods、MapPost、MapPut、Map等。

终结点

  上面讲的MapGet或者未用到MapPost等就是用于定义终结点的。它们都包含有两个参数,一个是用于Url匹配的,另外一个就是需要执行的委托。这里在不一样的应用中都采用了不同的终结点定义方法
    • 用于 Razor Pages 的 MapRazorPages
    • 用于控制器的 MapControllers
    • 用于 SignalR 的 MapHub
    • 用于 gRPC 的 MapGrpcService
  那么我们如果需要使用到了授权模块将如何处理呢,终结点也有相对应的处理方式。下面就展示将授权中间件和路由一起使用,MapHealthChecks添加运行状况检查终结点。后面跟着的RequireAuthorization则是将授权策略添加到端点。
  

           app.UseRouting();

            app.UseAuthentication();
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/healthz").RequireAuthorization();
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
  而且我们看中间的使用顺序,UseAuthentication、UseAuthorization是穿插在UseRoutingUseEndpoints中间的,如此写法则是为了授权策略能在UseRouting中查找终结点,但是能在UseEndpoints发送到终结点执行之前应用所选择的授权策略

终结点元数据

  上面的示例展示了运行状况检查终结点附加了授权策略。添加的授权策略是额外数据,也就是终结点元数据。
    • 可以通过路由感知中间件来处理元数据。
    • 元数据可以是任意的 .NET 类型。
  上面提到元数据可以是人意的.NET类型,那么具体到底是什么呢?元数据如何使用呢?
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.Use(next => context =>
{
var endpoint = context.GetEndpoint();
if (endpoint?.Metadata.GetMetadata<AuditPolicyAttribute>()?.NeedsAudit ==true)
{
Console.WriteLine("开始处理事务逻辑");
Console.WriteLine($"ACCESS TO SENSITIVE DATA AT: {DateTime.UtcNow}");
}
return next(context);
}); app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello world!");
}); // Using metadata to configure the audit policy.
endpoints.MapGet("/sensitive", async context =>
{
await context.Response.WriteAsync($"sensitive data{DateTime.UtcNow}");
})
.WithMetadata(new AuditPolicyAttribute(needsAudit: true));
});
}
} public class AuditPolicyAttribute : Attribute
{
public AuditPolicyAttribute(bool needsAudit)
{
NeedsAudit = needsAudit;
} public bool NeedsAudit { get; }
}
  看上面的示例中,在终结点绑定"/sensitive"的时候会附加元数据WithMetadata。当访问“/”的时候会输出"Hello world!"。但是在app.Use中并不会执行输出"处理事务逻辑",因为并没有匹配的元数据。但是当执行"/sensitive"的时候就会输出Console.WriteLine("开始处理事务逻辑");。因为在终结点定义的时候添加了元数据。元数据可以是人意.NET类型。上面的元数据也是我们自定义Class

比较终端中间件和路由

  上面我们使用app.Use来检测匹配元数据,如果匹配成功我们就执行对应的操作。我们称之为终端中间件,为什么是终端中间件呢,因为这里会停止搜索执行匹配和操作、最后返回。
  那么相比较下终端中间件和路由有什么区别呢?
    • 这两种方法都允许终止处理管道:终端中间件允许在管道中的任意位置放置中间件:

      • 中间件通过返回而不是调用 next 来终止管道。
      • 终结点始终是终端。
    • 终端中间件允许在管道中的任意位置放置中间件:

      • 终结点在 UseEndpoints 位置执行。
    • 终端中间件允许任意代码确定中间件匹配的时间:
      • 自定义路由匹配代码可能比较复杂,且难以正确编写。
      • 路由为典型应用提供了简单的解决方案。
      • 大多数应用不需要自定义路由匹配代码。
    • 带有中间件的终结点接口,如 UseAuthorization 和 UseCors。
      • 通过 UseAuthorization 或 UseCors 使用终端中间件需要与授权系统进行手动交互

设置传统路由

  上面我们知道了通过UseRouting向中间件添加路由匹配,然后通过UseEndpoints定义终结点去执行匹配委托。那么在MVC模式中如何设置呢?我们看看传统路由的设置方法。
         app.UseEndpoints(endpoints =>
{
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
});
  上面我们设置传统路由的时候采用的是endpoints.MapControllerRoute();,其中附带有两个参数,一个是名称default,第二个则是路由模板。我们看路由模板{controller=Home}/{action=Index}/{id?},那么在匹配Url路径的时候,例如执行路径 WeatherForecast/Index/5。那么则会匹配控制器为WeatherForecast,其中方法是Index并且参数是int类型的一个处理方法。

REST Api 的属性路由

  上面讲的是传统路由设置,那么对于Api项目的路由设置是如何的呢?REST Api 应使用属性路由将应用功能建模为一组资源。我们看下示例代码
  

     // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
  在上面的代码中使用MapControllers调用。映射属性路由。我们看在使用的时候属性路由的使用方式。
    1. Route[]
      下面的示例中我们采用的是Route[]的方式,它既可单独作用域控制器也可单独作用域action。也可同时使用。
  [ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{ [Route("Index")]
public string Index(int? id)
{
return "Test";
}
}
    [ApiController]
[Route("[controller]/[action]")]
public class WeatherForecastController : ControllerBase
{
public string Index(int? id)
{
return "Test";
}
}
    [ApiController]
public class WeatherForecastController : ControllerBase
{
[Route("[controller]/Index")]
public string Index(int? id)
{
return "Test";
}
}
    1. Http[Verb]
      采用Http[Verb]的方式那就仅仅能作用在action上了。比如下面的就直接在Index上方写[HttpGet("[controller]/Index")],其他就是HttpPost、HttpDelete等等操作
   [ApiController]
public class WeatherForecastController : ControllerBase
{
[HttpGet("[controller]/Index")]
public string Index(int? id)
{
return "Test";
}
}
    1. Route[]和Http[Verb]混合使用
      有时在实际运用中也可以采取两种方式混合使用的,例如下面的示例在控制器采用Route[],在action采用Http[Verb]。因为一般定义Api的时候我们不仅要标注action名称,我们还需要知道action的请求方式。
  [ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{ [HttpGet("Index")]
public string Index(int? id)
{
return "Test";
}
}
 

.Net Core 路由处理的更多相关文章

  1. ASP .Net Core路由(Route) - 纸壳CMS的关键

    关于纸壳CMS 纸壳CMS是一个开源免费的,可视化设计,在线编辑的内容管理系统.基于ASP .Net Core开发,插件式设计: GitHub:https://github.com/SeriaWei/ ...

  2. 构建可读性更高的 ASP.NET Core 路由

    原文:构建可读性更高的 ASP.NET Core 路由 一.前言 不知你在平时上网时有没有注意到,绝大多数网站的 URL 地址都是小写的英文字母,而我们使用 .NET/.NET Core MVC 开发 ...

  3. ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 路由 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 路由 前两章节中,我们提到 ASP.NET Core 支持 MVC 开发 ...

  4. ASP.NET Core路由中间件[3]: 终结点(Endpoint)

    到目前为止,ASP.NET Core提供了两种不同的路由解决方案.传统的路由系统以IRouter对象为核心,我们姑且将其称为IRouter路由.本章介绍的是最早发布于ASP.NET Core 2.2中 ...

  5. ASP.NET Core路由中间件[2]: 路由模式

    一个Web应用本质上体现为一组终结点的集合.终结点则体现为一个暴露在网络中可供外界采用HTTP协议调用的服务,路由的作用就是建立一个请求URL模式与对应终结点之间的映射关系.借助这个映射关系,客户端可 ...

  6. .Net core路由高级用法

    先说startup中的路由 这里是我们现在用的默认路由,但是在使用当中也有麻烦.总而言之 用的不爽. 使用属性路由:RouteAttribute特性 默认的HomeController下面的Index ...

  7. ASP.NET Core路由中间件[1]: 终结点与URL的映射

    目录 一.路由注册 二.设置内联约束 三.默认路由参数 四.特殊的路由参数 借助路由系统提供的请求URL模式与对应终结点(Endpoint)之间的映射关系,我们可以将具有相同URL模式的请求分发给应用 ...

  8. 理解ASP.NET Core - 路由(Routing)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 Routing Routing(路由):更准确的应该叫做Endpoint Routing,负责 ...

  9. Net core学习系列(六)——Net Core路由

    一.概述 路由主要有两个主要功能: 1.将请求的URL与已定义的路由进行匹配,找到该URL对应的处理程序并传入该请求进行处理. 2.根据已定义的路由生成URL 这两个功能看起来这两个是相反的. A.路 ...

  10. core路由设置

    全局路由设置 app.UseMvc(routes => { routes.MapRoute( name: "areas", template: "{area:exi ...

随机推荐

  1. GitHub & GitHub Package Registry

    GitHub & GitHub Package Registry npm https://github.blog/2019-05-10-introducing-github-package-r ...

  2. 为什么建议选择居住在墨尔本CBD以南2公里内

    英国房地产公司PAUL ADAMS ARCHITECT ,简称PPA(公司编号:07635831)成立于2011年,是一家成立近十年的老牌房地产公司.PAA公司一直有着自己的房地产理念,秉持房子是用来 ...

  3. ffmpeg中的日志控制、保存日志到指定文件、处理进度查询

    ffmpeg默认就会输出一些日志,包含编译的工具(gcc版本).可用的组件(--enable-xxxx).组件版本号码,如下图 这些信息是默认输出的,每次执行合作都会打印在控制台中,如果不想看这些信息 ...

  4. (转)linux下的系统调用函数到内核函数的追踪

    转载网址:http://blog.csdn.net/maochengtao/article/details/23598433 使用的 glibc : glibc-2.17使用的 linux kerne ...

  5. 使用dlopen加载动态库

    目录 概述 接口 C CMakeLists.txt src/main.c src/add.c ./dlopen_test C++ CMakeLists.txt src/main.cpp src/add ...

  6. 一个基于 Vue3 的开源项目,3个月时间 star 终于破千!

    本文主要是对如何做开源项目的一些思考. 前文回顾: <Vue3 来了,Vue3 开源商城项目重构计划正式启动!> <一个基于 Vue 3 + Vant 3 的开源商城项目> 关 ...

  7. 《C++ Primer》笔记 第12章 动态内存

    shared_ptr和unique_ptr都支持的操作 解释 shared_ptr sp或unique_ptr up 空智能指针,可以指向类型为T的对象 p 将p用作一个条件判断,若p指向一个对象,则 ...

  8. CCF(除法):线段树区间修改(50分)+线段树点修改(100分)+线段树(100分)

    除法 201709-5 这道题有很多种方法来做,最常用的就是线段树和树状数组. 如果使用线段树来做,就会想到区间修改的update函数.但是这里可能会涉及到v是1或者a[j]是0的情况,所以用这种方法 ...

  9. HDOJ-6665(离散化+DFS求连通分量)

    Calabash and Landlord HDOJ-6665 这里考察的是离散化的知识. 首先将所有的x坐标和y坐标放入两个数组中,然后对这两个数组进行排序.因为总共的坐标数就5个所以这两个数组的大 ...

  10. pytorch(02)tensor的概念以及创建

    二.张量的简介与创建 2.1张量的概念 张量的概念:Tensor 张量是一个多维数组,它是标量.向量.矩阵的高维拓展 Tensor与Variable Variable是torch.autograd(t ...