ASP.NET Core 2.2中的Endpoint路由
Endpoint路由
在ASP.NET Core 2.2中,新增了一种路由,叫做Endpoint
(终结点)路由。本文将以往的路由系统称为传统路由
。
本文通过源码的方式介绍传统路由和Endpoint
路由部分核心功能和实现方法,具体功能上的差异见官方文档。
在升级到ASP.NET Core 2.2后,会自动启用Endpoint
路由。如果要恢复以往的实现逻辑,需要加入以下代码:
services.AddMvc(options => options.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
本文分析的源代码基于ASP.NET Core 2.2.3版本的源代码。
Endpoint作用
Endpoint
路由与传统路由的区别在于,传统路由Url
与Action
对应关系的处理是在UseMvc
中做的。我们无法根据Url
获取对应的Action
然后进行处理。
Endpoint
就是将Url
与Action
的映射关系从Mvc
中拆离,作为独立使用的中间件。
由此带来的好处是我们可以在其他的中间件中使用Controller
和Action
上的一些信息,例如Attruibute
。
框架也提供了LinkGenerator
类来直接根据Endpoint
生成链接,不再需要HttpContext
的信息。
另外也提升了一些RPS(Requests per Second)。
不过目前Endpoint
依然是在UseMvc
中调用,更多开放的使用方式会在ASP.NET Core 3.0中实现。
启用Endpoint路由
源代码见Github。也可以获取源代码到本地看。
在MvcApplicationBuilderExtensions.cs
文件72行的UseMvc
方法中我们可以看到以下代码:
var options = app.ApplicationServices.GetRequiredService<IOptions<MvcOptions>>();
if (options.Value.EnableEndpointRouting)
{
...
}
else
{
...
}
if
之中是Endpoint
路由的逻辑,else
是传统路由的逻辑。
而MvcOptions
的构造方法如下所示,EnableEndpointRouting
是通过CompatibilitySwitch
来控制默认值的,这就是CompatibilityVersion.Version_2_2
启用Endpoint
路由的原因。
public MvcOptions()
{
// ...
_enableEndpointRouting = new CompatibilitySwitch<bool>(nameof(EnableEndpointRouting));
// ...
}
Endpoint路由实现原理
在MvcApplicationBuilderExtensions.cs
文件的92-123行的代码是将所有的Controller
中的Action
转换成Endpoint
。
在129行的UseEndpointRouting
中,添加了一个EndpointRoutingMiddleware
的中间件,这个中间件就是从所有的Endpoint
中找到当前路由对应的Endpoint
,然后放到Feature
集合中。
在132行的UseEndpoint
中,添加了一个EndpointMiddleware
中间件,这个中间件是将EndpointRoutingMiddleware
中找到的Endpoint
取出,并调用RequestDelegate
。RequestDelegate
是预处理过的Url
对应的Action
方法。
在UseMvc
方法里,UseEndpointRouting
和UseEndpoint
是连续的两个中间件,而UseEndpoint
是请求的结束,这意味着我们自定义的中间件无法取得Endpoint
信息。
但是通过手动调用UseEndpointRouting
,我们还是可以拿到Endpoint
路由信息的。
使用示例
下面展示一个使用示例。
定义一个LogAttribute
类,并包含一个Message
属性,在Action
上声明使用。
定义一个EndpointTestMiddleware
中间件,输出LogAttribute
的Message
属性。
手动调用UseEndpointRouting
,然后调用我们定义的EndpointTestMiddleware
中间件。
// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseEndpointRouting();
app.UseMiddleware<EndpointTestMiddleware>();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
// EndpointTestMiddleware.cs
public class EndpointTestMiddleware
{
private RequestDelegate _next;
public EndpointTestMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
var endpoint = httpContext.Features.Get<IEndpointFeature>()?.Endpoint;
if (endpoint == null)
{
await _next(httpContext);
return;
}
var attruibutes = endpoint.Metadata.OfType<LogAttribute>();
foreach (var attribute in attruibutes)
{
Debug.WriteLine("------------------------------------------------------------------------");
Debug.WriteLine(attribute.Message);
Debug.WriteLine("------------------------------------------------------------------------");
}
await _next(httpContext);
}
}
// LogAttribute.cs
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
public sealed class LogAttribute : Attribute
{
public LogAttribute(string message)
{
Message = message;
}
public string Message { get; set; }
}
// HomeController.cs
public class HomeController : Controller
{
[Log("Index")]
public IActionResult Index()
{
return View();
}
[Log("Privacy")]
public IActionResult Privacy()
{
return View();
}
}
这样的话,我们可以在我们自己的中间件中拿到Endpoint
信息,然后找到Controller
上的LogAttribute
,然后输出Message
。
总结
Endpoint
是ASP.NET Core 2.2中一种新的路由机制,它解决了传统路由难以扩展的问题,解决了传统路由与MVC过于耦合的问题,并提升了一定的RPS。
本文介绍了Endpoint路由,简单分析了Endpoint的实现原理,并给出了一个使用的示例。
参考链接:
- https://devblogs.microsoft.com/aspnet/asp-net-core-2-2-0-preview1-endpoint-routing/
- https://www.stevejgordon.co.uk/asp-net-core-first-look-at-global-routing-dispatcher
- https://rolandguijt.com/endpoint-routing-in-asp-net-core-2-2-explained/
ASP.NET Core 2.2中的Endpoint路由的更多相关文章
- ASP.NET Core 3.0中使用动态控制器路由
原文:Dynamic controller routing in ASP.NET Core 3.0 作者:Filip W 译文:https://www.cnblogs.com/lwqlun/p/114 ...
- 避免在ASP.NET Core 3.0中为启动类注入服务
本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇. Part 1 - 将.NET Standard 2.0类库转换为.NET Core 3.0类库 Part 2 - IHostingE ...
- asp.net core 3.0 中使用 swagger
asp.net core 3.0 中使用 swagger Intro 上次更新了 asp.net core 3.0 简单的记录了一下 swagger 的使用,那个项目的 api 比较简单,都是匿名接口 ...
- 探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs
原文:探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs 前言:.NET Core 3.0 SDK包含比以前版本更多的现成模板. 在本文中,我将 ...
- 将终结点图添加到你的ASP.NET Core应用程序中
在本文中,我将展示如何使用DfaGraphWriter服务在ASP.NET Core 3.0应用程序中可视化你的终结点路由.上面文章我向您演示了如何生成一个有向图(如我上篇文章中所示),可以使用Gra ...
- ASP.NET Core HTTP 管道中的那些事儿
前言 马上2016年就要过去了,时间可是真快啊. 上次写完 Identity 系列之后,反响还不错,所以本来打算写一个 ASP.NET Core 中间件系列的,但是中间遇到了很多事情.首先是 NPOI ...
- ASP.NET Core 1.0 中的依赖项管理
var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...
- 在ASP.NET Core 1.0中如何发送邮件
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:目前.NET Core 1.0中并没有提供SMTP相关的类库,那么要如何从ASP.NE ...
- ASP.NET Core 1.0 中使用 Swagger 生成文档
github:https://github.com/domaindrivendev/Ahoy 之前文章有介绍在ASP.NET WebAPI 中使用Swagger生成文档,ASP.NET Core 1. ...
随机推荐
- 深入理解Java中的IO
深入理解Java中的IO 引言: 对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务 < Thinking in Java > 本文的目录视图如下: ...
- ide调试
F8: 程序向下执行一行(如果当前行有方法调用,这个方法将被执行完毕返回,然后到下一行) F7: 程序向下执行一行.如果该行有自定义方法,则运行进入自定义方法(不会进入官方类库的方法) Alt + ...
- VS2010 Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)
步骤如下: 1. Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)" title="VS2010 Chart控件(一)Chart控件在ASP.NE ...
- java项目打成war包
1.修改pom.xml下的打包方式 <groupId>com.test</groupId> <artifactId>springboot</artifactI ...
- 坑之mysql 字符串与数字操作
select "123"+1 = 124; select "1a23"+1 = 2; select "aa23"+1 = 1; select ...
- OpenStack 安装:基本环境准备
刚刚学完openstack,这几篇文章就算对过去课程的一个总结吧. 首先说说基本的结构:在一台Dell的workstation上面安装了VMware,在VMware上面安装两台CentOS,现在给每台 ...
- Educational Codeforces Round 63-D(基础DP)
题目链接:https://codeforces.com/contest/1155/problem/D 题意:给定n个数,可以选择一段连续子段将其乘x,也可以不操作,求最大连续子段和. 思路:比赛时觉得 ...
- 在VMware的虚拟机中克隆CentOS,在重启网卡的时候报错解决办法
克隆虚拟机配置 1.修改:vi /etc/hosts 2.修改:vi /etc/sysconfig/network 3.重启生效:reboot或者init 6 如不重启可以输入:hostname 新 ...
- PHP Laravel定时任务Schedule
前提:本文方法是利用Linux的crontab定时任务来协助实现Laravel调度(Mac也一样). 一.首先添加Crontab定时任务,这里只做简单介绍. 用命令crontab -e 添加如下内容 ...
- [leetcode]4. Median of Two Sorted Arrays俩有序数组的中位数
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...