一、管道
路由、认证、会话、缓存等等,他们都是通过管道来实现的ASP.NET Core 应用一般都是使用某个框架来开发,MVC、Web API,建立在某个特殊的中间件之上。通过编写中间件,扩展请求管道,在ASP.NET Core上创建我们自己的WEB框架,API网关Ocelot,API网关框架。Middleware两个职责:1、选择是否将请求传递给管道中的下一个中间件2、在管道中的下一个中间件的前后执行工作。
每个中间件都有权作出决定是否将请求传递给下一个中间件,也可以直接作出响应,管道的短路。
短路就是指不再将请求继续往下传递,而是结束请求并开始响应。
短路时非常有必要
二、运用原理
1、app.RunRun相当于一个终结点,Run之后的中间件不会被执行,因为它不像Use一样可以调用next.Invoke(); //接收一个委托 参数:http上下文对象 这个委托就是中间件
//Adds a terminal middleware delegate to the application's request pipeline
//向应用程序的请求管道添加终端中间件委托 (添加是一个终端(终结点)中间件)
app.Run(async context =>
{
await context.Response.WriteAsync("Hello Run");
});
2、app.Use传入的委托中含有一个委托参数,我们一般用next来接收这个委托参数,通过调用next.Invode()方法来调用下一个中间件,这样Use之后的中间件才能够被执行
//Adds a terminal middleware delegate to the application's request pipeline
//next 指向下一个中间件
app.Use(async (context, next) =>
{
// 请求处理
await context.Response.WriteAsync("Middleware 1 Begin");
await next();
// 响应 (返回的时候)
await context.Response.WriteAsync("Middleware 1 End");
});
3、app.Map只有访问特定的路径才会执行
app.Map("/map", app =>
{
app.Run(context =>
{
Console.WriteLine("map-run");
return Task.FromResult("run done");
});
});
3、所谓的中间件,其实就是一堆委托
4、
//注册自定义中间件
app.UseMiddleware<>(自定义的中间件类);
5、中间件的顺序,管道里的中间是有顺序的。就是我们代码的顺序顺序是很重要
6、
// 内置一个依赖注入框架,添加内置中间件
// 这个中间件,他依赖一些服务类,是通过依赖注入注入进来
// 跨域中间件 需要先注册服务 在ConfigureServices services.AddCors();
app.UseCors();
中间件所依赖的类,都可以通过服务容器注入7、路由中间件
// 终端路由中间件
//mvc 核心中间件 路由中间件
// 识别路由,匹配路由和终结点
// 通用的
app.UseRouting();
//UseEndpoints 向中间件管道添加终结点执行。 它会运行与所选终结点关联的委托。
// 终结点中间件
// 终结点 ,可以视为应用程序提供针对HTTP请求的处理器
// MVC应用,终结点就对应着控制器中的某个方法
// WebAPI
// 可配置的
app.UseEndpoints(endpoints =>
{
//mvc 核心中间件
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
8、自定义中间件!
// 按照约定来创建
// 具有类型为RequestDelegate的参数的公共构造函数
// 名为Invoke或者InvokeAsync的公共方法,这个方法必须满足两个条件:返回Task;接受类型HttpContext的第一个参数;
public class MarkdownMiddleware
{
private readonly RequestDelegate next;
private readonly IWebHostEnvironment hostEn;
public MarkdownMiddleware(RequestDelegate next, IWebHostEnvironment hostEnv)
{
this.next = next;
this.hostEn = hostEnv;
}
public async Task InvokeAsync(HttpContext context)
{
string path = context.Request.Path.ToString();
//只处理.md文件请求
if (!path.EndsWith(".md", true, null))
{
await next.Invoke(context);
return;
}
//是否存在文件流
var file = hostEn.WebRootFileProvider.GetFileInfo(path);
if (!file.Exists)
{
await next.Invoke(context);
return;
}
//ude.netstandard 检测流的编码
using var stream = file.CreateReadStream();
Ude.CharsetDetector cdet = new Ude.CharsetDetector();
cdet.Feed(stream);
cdet.DataEnd();
//探测文本编码类型
string charset = cdet.Charset ?? "UTF-8";
//复位,因为CharsetDetector已经把stream的指针往后挪了
//因为后面要重新读这个流
stream.Position = 0;
using StreamReader reader = new StreamReader(stream, Encoding.GetEncoding(charset));
//读取md问题
string mdTest = await reader.ReadToEndAsync();
Markdown md = new Markdown();
//md-》html
string html = md.Transform(mdTest);
context.Request.ContentType = "test/hem;charset=UTF-8";
await context.Response.WriteAsync(html);
}
}
使用 在 Startup.cs 中 Configure 添加 //中间件 md转换器
app.UseMiddleware<MarkdownMiddleware>();
9、扩展方法创建一个类扩展 public static class CostomMiddlewareExtensions
{
//扩展方法
public static IApplicationBuilder UseTest(this IApplicationBuilder app)
{
return app.UseMiddleware<MarkdownMiddleware>();
}
}
使用 app.UseTest();
10、你编写WEB应用,实际就是再写中间件。。全都是中间件。。你写的控制器,也是中间件里的一部分。整个ASP.NET Core应用,都是在管道里运行的管道里放的都是中间件11、源码https://github.com/dotnet/aspnetcoreUse 实际是通过委托将 _components 集合添加(有两个USE,每个USE 都是在_components 列表里,把委托添加到进去,别的啥也没有干没有关系,两个独立的Func委托,现在还不是真正中间件)Build 构造管道方法 方法中:先加一个默认(底层)中间件 为了报错 后 管道就是这两句话构成的、 挨个执行Func委托,然后把前一个中间件,塞到后一个委托中,这样遍历执行 中间件委托就形成了一条链子,责任链模式<设计模式>:流程化 组成了一个责任链 最后一个被执行的,是第一个中间件,把第一个中间件返回出去了 当我们请求进来的时候,由主机创建HTTP上下文对象,然后把上下文对象赛到第一个中间件
这里是倒叙遍历
for (var c = _components.Count - 1; c >= 0; c--)
{
app = _components[c](app);
}
(底层)中间件传个2号中间件的委托,包含有链子的中间件就被创建出来,把2号中间件返回出来 1号->2号->底层->2号->1号标签:CORE,委托,app,中间件,next,管道,context,NET From: https://www.cnblogs.com/buzheng11/p/17661691.html