- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章ASP.NET Core Middleware的实现方法详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
概念 。
ASP.NET Core Middleware是在应用程序处理管道pipeline中用于处理请求和操作响应的组件.
每个组件:
特性和行为 。
ASP.NET Core处理管道由一系列请求委托组成,一环接一环的被调用, 下面给出自己绘制的Middleware pipeline流程图:
从上图可以看出,请求自进入处理管道,经历了四个中间件,每个中间件都包含后续紧邻中间件 执行委托(next)的引用,同时每个中间件在交棒之前和交棒之后可以自行决定参与一些Http请求和响应的逻辑处理.
每个中间件还可以决定不将请求转发给下一个委托,这称为请求管道的短路(短路是有必要的,某些专有中间件比如 StaticFileMiddleware 可以在完成功能之后,避免请求被转发到其他动态处理过程).
源码实现 。
观察一个标准的中间件代码的写法和用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
using
System.Threading.Tasks;
using
Alyio.AspNetCore.ApiMessages;
using
Gridsum.WebDissector.Common;
using
Microsoft.AspNetCore.Http;
namespace
Gridsum.WebDissector
{
sealed
class
AuthorizationMiddleware
{
private
readonly
RequestDelegate _next;
// 下一个中间件执行委托的引用
public
AuthorizationMiddleware(RequestDelegate next)
{
_next = next;
}
public
Task Invoke(HttpContext context)
// 贯穿始终的HttpContext对象
{
if
(context.Request.Path.Value.StartsWith(
"/api/"
))
{
return
_next(context);
}
if
(context.User.Identity.IsAuthenticated && context.User().DisallowBrowseWebsite)
{
throw
new
ForbiddenMessage(
"You are not allow to browse the website."
);
}
return
_next(context);
}
}
}
public
static
IApplicationBuilder UserAuthorization(
this
IApplicationBuilder app)
{
return
app.UseMiddleware<AuthorizationMiddleware>();
}
// 启用该中间件,也就是注册该中间件
app.UserAuthorization();
|
标准的中间件使用方式是如此简单明了,带着几个问题探究一下源码实现 。
(1).中间件传参是怎样完成的: app.UseMiddleware<Authorization>(AuthOption); 我们传参的时候,为什么能自动注入中间件构造函数非第1个参数 。
(2).编写中间件的时候,为什么必须要定义特定的 Invoke/InvokeAsync 函数?
(3).设定中间件的顺序很重要,中间件的嵌套顺序是怎么确定的 ?
。
思考以上标准中间件的行为: 输入下一个中间件的执行委托Next, 定义当前中间件的执行委托Invoke/InvokeAsync; 。
每个中间件完成了 Func<RequestDelegate,RequestDelegate>这样的行为; 。
通过参数next与下一个中间件的执行委托Invoke/InvokeAsync 建立"链式"关系.
public delegate Task RequestDelegate(HttpContext context),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
//-----------------节选自 Microsoft.AspNetCore.Builder.UseMiddlewareExtensions------------------
/// <summary>
/// Adds a middleware type to the application's request pipeline.
/// </summary>
/// <typeparam name="TMiddleware">The middleware type.</typeparam>
/// <param name="app">The <see cref="IApplicationBuilder"/> instance.</param>
/// <param name="args">The arguments to pass to the middleware type instance's constructor.</param>
/// <returns>The <see cref="IApplicationBuilder"/> instance.</returns>
public
static
IApplicationBuilder UseMiddleware<TMiddleware>(
this
IApplicationBuilder app,
params
object
[] args)
{
return
app.UseMiddleware(
typeof
(TMiddleware), args);
}
/// <summary>
/// Adds a middleware type to the application's request pipeline.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> instance.</param>
/// <param name="middleware">The middleware type.</param>
/// <param name="args">The arguments to pass to the middleware type instance's constructor.</param>
/// <returns>The <see cref="IApplicationBuilder"/> instance.</returns>
public
static
IApplicationBuilder UseMiddleware(
this
IApplicationBuilder app, Type middleware,
params
object
[] args)
{
if
(
typeof
(IMiddleware).GetTypeInfo().IsAssignableFrom(middleware.GetTypeInfo()))
{
// IMiddleware doesn't support passing args directly since it's
// activated from the container
if
(args.Length > 0)
{
throw
new
NotSupportedException(Resources.FormatException_UseMiddlewareExplicitArgumentsNotSupported(
typeof
(IMiddleware)));
}
return
UseMiddlewareInterface(app, middleware);
}
var applicationServices = app.ApplicationServices;
return
app.Use(next =>
{
var methods = middleware.GetMethods(BindingFlags.Instance | BindingFlags.Public);
// 执行委托名称被限制为Invoke/InvokeAsync
var invokeMethods = methods.Where(m =>
string
.Equals(m.Name, InvokeMethodName, StringComparison.Ordinal)
||
string
.Equals(m.Name, InvokeAsyncMethodName, StringComparison.Ordinal)
).ToArray();
if
(invokeMethods.Length > 1)
{
throw
new
InvalidOperationException(Resources.FormatException_UseMiddleMutlipleInvokes(InvokeMethodName, InvokeAsyncMethodName));
}
if
(invokeMethods.Length == 0)
{
throw
new
InvalidOperationException(Resources.FormatException_UseMiddlewareNoInvokeMethod(InvokeMethodName, InvokeAsyncMethodName, middleware));
}
var methodInfo = invokeMethods[0];
if
(!
typeof
(Task).IsAssignableFrom(methodInfo.ReturnType))
{
throw
new
InvalidOperationException(Resources.FormatException_UseMiddlewareNonTaskReturnType(InvokeMethodName, InvokeAsyncMethodName, nameof(Task)));
}
var parameters = methodInfo.GetParameters();
if
(parameters.Length == 0 || parameters[0].ParameterType !=
typeof
(HttpContext))
{
throw
new
InvalidOperationException(Resources.FormatException_UseMiddlewareNoParameters(InvokeMethodName, InvokeAsyncMethodName, nameof(HttpContext)));
}
var ctorArgs =
new
object
[args.Length + 1];
ctorArgs[0] = next;
Array.Copy(args, 0, ctorArgs, 1, args.Length);
// 通过反射形成中间件实例的时候,构造函数第一个参数被指定为 下一个中间件的执行委托 var instance = ActivatorUtilities.CreateInstance(app.ApplicationServices, middleware, ctorArgs);
if
(parameters.Length == 1)
{
return
(RequestDelegate)methodInfo.CreateDelegate(
typeof
(RequestDelegate), instance);
}
// 当前执行委托除了可指定HttpContext参数以外, 还可以注入更多的依赖参数
var factory = Compile<
object
>(methodInfo, parameters);
return
context =>
{
var serviceProvider = context.RequestServices ?? applicationServices;
if
(serviceProvider ==
null
)
{
throw
new
InvalidOperationException(Resources.FormatException_UseMiddlewareIServiceProviderNotAvailable(nameof(IServiceProvider)));
}
return
factory(instance, context, serviceProvider);
};
});
}
//-------------------节选自 Microsoft.AspNetCore.Builder.Internal.ApplicationBuilder-------------------
private
readonly
IList<Func<RequestDelegate, RequestDelegate>> _components =
new
List<Func<RequestDelegate, RequestDelegate>>();
publicIApplicationBuilder Use(Func<RequestDelegate,RequestDelegate>middleware)
{
this
._components.Add(middleware);
return
this
;
}
public
RequestDelegate Build()
{
RequestDelegate app = context =>
{
context.Response.StatusCode = 404;
return
Task.CompletedTask;
};
foreach
(var component
in
_components.Reverse())
{
app = component(app);
}
return
app;
}
|
通过以上代码我们可以看出:
Type= List<Func<RequestDelegate, RequestDelegate>>
的容器依次添加元素的过程;Func<RequestDelegate, RequestDelegate>
, 这个行为委托包含2个关键行为:输入下一个中间件的执行委托next:RequestDelegate
, 完成当前中间件的Invoke函数: RequestDelegate;
分析源码:回答上面的问题:
附:非标准中间件的用法 。
短路中间件、 分叉中间件 。
整个处理管道的形成,存在一些管道分叉或者临时插入中间件的行为,一些重要方法可供使用 。
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:https://www.cnblogs.com/mi12205599/p/10334472.html 。
最后此篇关于ASP.NET Core Middleware的实现方法详解的文章就讲到这里了,如果你想了解更多关于ASP.NET Core Middleware的实现方法详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
主要思想是将 EF Core nuget 包添加到 .NET Core 库项目,然后在一堆应用程序(例如 ASP.NET Core、Win 服务、控制台应用程序)中使用该库,而无需在每个应用程序中配置
我想要实现的是编写一个简单的.net核心后台工作程序(.net core 3.1)的代码,在该工作程序作为Windows服务运行时,我在其中将数据写入SQL Server数据库(通过EF Core 3
关于 .Net Core SDK download page 二进制文件有什么用?它与安装程序有何不同? 最佳答案 二进制文件是 .NET Core 的编译代码。它们拥有运行 .NET Core 所需
.NET Core 和 Entity Framework Core 之间的区别?我们可以在 .NET Core 中使用 Entity Framework Core 吗?两者都有什么优势? 最佳答案 E
.NET Core 和 ASP.NET Core 到底有什么区别? 它们是相互排斥的吗?我听说 ASP.NET Core 是基于 .NET Core 构建的,但它也可以基于完整的 .NET 框架构建。
我对 ASP.NET Core 开发完全陌生。我正在尝试使用单个模型和 mysql 创建一个简单的 asp.net core Web api 来存储模型数据,然后我想使用 Swagger 将其作为 R
.NET Core 和 Entity Framework Core 之间的区别?我们可以在 .NET Core 中使用 Entity Framework Core 吗?两者都有什么优势? 最佳答案 E
好吧,作为一个新的 .net 开发生态系统,我有点迷失在核心工具、版本等方面。 有人可以解释我之间的区别吗 VS 2015 核心工具预览版 x - See here .NET Core/SDK 与否
我已阅读有关如何通过信号器核心集线器从后台服务向客户端发送通知的文档。如何从客户端接收到后台服务的通知? 后台服务应该只是一个单例。 public class Startup { public
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 4年前关闭。 Improve t
非常简单的问题: 我正在尝试创建一个像这样的谓词构建器: var predicate = PredicateBuilder.False(); 但似乎在Net Core和EF Core中不可用。
在 .NET Core 自包含应用程序 中...我们需要在 project.json 中指定运行时 (RID) 我们希望我们的应用程序针对...发布为什么会这样? .NET Core 是跨平台的,与我
如何用 iCloud Core Data 替换我现有的 Core Data?这是我的持久商店协调员: lazy var persistentStoreCoordinator: NSPersistent
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 2 年前。 Improv
今天我正在学习新的 ASP.net 核心 API 3.1,我想将我的旧网站从 MVC4 转移到 Web API。除了一件事,一切都很好。数据库连接。在我的旧网站中,我为每个客户端(10/15 数据库)
我在 Visual Studio 2015 Update 3 和 .NET Core 1.0 中工作。我有一个 .NETCoreApp v1.0 类型的 Web API 项目。当我添加一个 .NET
我一直在尝试遵循 Ben Cull ( http://benjii.me/2016/06/entity-framework-core-migrations-for-class-library-proj
当我打开我的 vs 代码程序时,我收到以下消息: 无法找到 .NET Core SDK。 .NET Core 调试将不会启用。确保 .NET Core SDK 已安装并且在路径上。 如果我安装甚至卸载
我偶然发现了一个非常奇怪的问题。每当 Web 应用程序启动时,dotnet.exe 都会使用相当多的内存(大约 300M)。然而,当它触及某些部分时(我感觉这与 EF Core 使用有关),它会在短时
ASP.NET Core Web (.NET Core) 与 ASP.NET Core Web (.NET Framework) 有什么区别? .NET Framework 是否提供 similar
我是一名优秀的程序员,十分优秀!