ASP.NET Core 中间件

中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:
1.选择是否将请求传递到管道中的下一个组件。
2.可在管道中的下一个组件前后执行工作。
请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。
使用 Run 、Map 和 Use 扩展方法来配置请求委托。 可将一个单独的请求委托并行指定为匿名方法(称为中间件),或在可重用的类中对其进行定义。 这些可重用的类和并行匿名方法即为中间件 ,也叫中间件组件 。 请求管道中的每个中间件组件负责调用管道中的下一个组件,或使管道短路。 当中间件短路时,它被称为“终端中间件” ,因为它阻止中间件进一步处理请求。

使用中间件#

ASP.NET Core中间件模型是我们能够快捷的开发自己的中间件,完成对应用的扩展,我们先从一个简单的例子了解一下中间件的开发。

Run:

作用:第一个 Run 委托终止了管道。

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello, World!");
        });
    }
}

运行结果:

这样的结果看起来不能明显的显示出Run的作用,接下来我们再介绍一个简单的例子:


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
       
                app.Run(async context =>
                {
                    await context.Response.WriteAsync("Hello, .Net");
                });
                app.Run(async context =>
                {
                    await context.Response.WriteAsync("Hello, Python!");
                });



          
}

运行结果:

 通过这两段简单的代码可看出,使用Run方法运行一个委托,就是一个简单的中间件,它拦截了所有请求,返回一段文本作为响应。并且Run委托终止了管道的运行,因此也叫作终端中间件。

Use

        
Use 将多个请求委托链接在一起。next 参数表示管道中的下一个委托。可通过不调用 next 参数使管道短路。通常可在下一个委托前后执行操作,如以下示例所示:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

	app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use1 \r\n");
		//await next.Invoke();
		await context.Response.WriteAsync("After Use1 \r\n");
		// Do logging or other work that doesn't write to the Response.
	});

	app.Run(async context =>
	{
		await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");
	});

}

代码执行结果:

有没有想到结果会是这样的?各位是不是会说Run 才是终止中间件,为什么没有显示其相应的内容呢?大家思考一下。。。。

 

 

 

 

 

 

 

 

 

相信大家应该都猜到了,之前我们在介绍Use的时候说到了

Use 将多个请求委托链接在一起。next 参数表示管道中的下一个委托。可通过不调用 next 参数使管道短路。

 

接下来我们再看下一个例子:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

   
	app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use1 \r\n");
		await next.Invoke();
	   
	});
	app.Run(async context =>
	{
		await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");
	});

}

运行结果大家猜一下会是什么?相信大家都可以才得到,就不粘贴结果了,可以自己实验一下

 

中间件顺序

ASP.NET Core 请求管道包含一系列请求委托,依次调用。 下图演示了这一概念。 沿黑色箭头执行。

向 Startup.Configure 方法添加中间件组件的顺序定义了针对请求调用这些组件的顺序,以及响应的相反顺序。 此顺序对于安全性、性能和功能至关重要。

接下来我们看例子:

 

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

   
	app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use1 \r\n");
		await next.Invoke();
		await context.Response.WriteAsync("After Use1 \r\n");
	   
	});
	app.Run(async context =>
	{
		await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");
	});

}

运行结果:

可能通过上面的实验还不能很明白中间件的执行顺序,我们再来一个例子:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

   app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use \r\n");
		await next.Invoke();
		await context.Response.WriteAsync("After Use \r\n");
		// Do logging or other work that doesn't write to the Response.
	});
	app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use1 \r\n");
		await next.Invoke();
		await context.Response.WriteAsync("After Use1 \r\n");
	   
	});
	app.Run(async context =>
	{
		await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");
	});

}

运行结果:

通过这两个的实验对比,我们就可以发现,中间件的运行顺序是顺时针的,中间件中,next之前的是按照中间件的排序顺序从上到下依次执行,在next之后的代码是按照中间件的反序进行执行的。

自定义 ASP.NET Core 中间件

中间件通常封装在一个类中,并使用扩展方法进行暴露。

中间件委托移动到类:

在Middlewares中创建RequestMiddlewareExtensions类:

public class RequestTestMiddleware
{
	private readonly RequestDelegate _next;
	public RequestTestMiddleware(RequestDelegate next)
	{
		_next = next;
	}
	public async Task InvokeAsync(HttpContext context)
	{
	   
		await context.Response.WriteAsync("start RequestTestMiddleware  \r\n");
		
		await _next(context);
		await context.Response.WriteAsync("end  RequestTestMiddleware \r\n");
	}
}

将中间件按照以下方式插入:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
	// app.UseRequestCulture();
	app.UseMiddleware<RequestTestMiddleware>();
	app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use \r\n");
		await next.Invoke();
		await context.Response.WriteAsync("After Use \r\n");
		// Do logging or other work that doesn't write to the Response.
	});

	app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use1 \r\n");
		await next.Invoke();
		await context.Response.WriteAsync("After Use1 \r\n");
		// Do logging or other work that doesn't write to the Response.
	});

	app.Run(async context =>
	{
		await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");
	});
   
}

 执行结果:

通过扩展方法暴露中间件: 

编写扩展方法RequestMiddlewareExtensions

public static  class RequestMiddlewareExtensions
{
	public static IApplicationBuilder UseRequestCulture(
		this IApplicationBuilder builder)
	{
		return builder.UseMiddleware<RequestTestMiddleware>();
	}
}

在Startup类中创建应用的请求处理管道:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
	app.UseRequestCulture();
	//app.UseMiddleware<RequestTestMiddleware>();
	app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use \r\n");
		await next.Invoke();
		await context.Response.WriteAsync("After Use \r\n");
		// Do logging or other work that doesn't write to the Response.
	});

	app.Use(async (context, next) =>
	{
		// Do work that doesn't write to the Response.
		await context.Response.WriteAsync("before Use1 \r\n");
		await next.Invoke();
		await context.Response.WriteAsync("After Use1 \r\n");
		// Do logging or other work that doesn't write to the Response.
	});

	app.Run(async context =>
	{
		await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");
	});
   
}

 

执行结果同上。


这是我的微信公共号,希望和大家一起成长,我会保持一天左右更新一次。 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值