前言

ASP.NET Core 中 HTTP 管道使用中间件组合处理的方式,

换句人话来说,

对于写代码的人而言,一切皆中间件.

业务逻辑/数据访问/等等一切都需要以中间件的方式来呈现.

那么我们必须学会如何实现自定义中间件 这里划重点,必考

这里我们介绍下中间件的几种实现方式...

匿名函数

通常新建一个空的 ASP.NET Core Web Application,项目名字无所谓啦

在启动类里可以看到这么一句:

// Startup.cs
// ...
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
// ...

这就是一个匿名函数实现的中间件,虽然内容比较少.

可以看到通过匿名函数实现的中间件是内嵌在启动类文件中的,因此通常也叫做内联中间件

接下来,我们通过匿名函数来实现内联中间件,以便加深理解.

新建一个空的 ASP.NET Core Web Application

然后修改启动类代码如下:

// Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System; namespace WebApplication1
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} // 使用匿名函数实现一个内联中间件
app.Use(async (context, next) =>
{
throw new NotImplementedException("一个使用匿名函数,但未实现具体内容的内联中间件");
}); app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
}

这里我们在 app.Run 之前使用 app.Use 添加一个匿名函数实现的内联中间件,按照中间件的注册顺序,当发起请求时,会抛出一个异常 NotImplementedException("一个使用匿名函数,但未实现具体内容的内联中间件")

我们 F5 启动下,看看页面

嗯,符合预期.

我们再来调整下启动类,代码如下:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; namespace WebApplication1
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} // 使用匿名函数实现一个内联中间件
app.Use(async (context, next) =>
{
// 这里不对 request 做任何处理,直接调用下一个中间件
await next.Invoke();
}); app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
}

这里我们在 app.Run 之前使用 app.Use 添加一个匿名函数实现的内联中间件,该中间件没有对 request 做任何处理,只是一个空的空间件,按照中间件的注册顺序,当发起请求时,页面应该显示 Hello World!.

我们 F5 启动,看看效果

嗯,符合预期.

个人觉得:匿名函数不是很直观,但是用内联的方式可以快速开始一些开发,不用新建一个中间件类,不用专门想个不一样的名字,小场景下是非常方便实用的

实现接口

通过实现接口 IMiddleware 编写自定义中间件,这是一种强类型的方式,我们需要必须强制按照接口的定义来实现.

IMiddleware

接口 IMiddleware 定义如下:

using System.Threading.Tasks;

namespace Microsoft.AspNetCore.Http
{
public interface IMiddleware
{
Task InvokeAsync(HttpContext context, RequestDelegate next);
}
}

可以看到接口 IMiddleware 的命名空间是 Microsoft.AspNetCore.Http,需要实现的方法是InvokeAsync(),看起来不算太复杂, 嗯,看起来不算太复杂

嗯,重新开始,我们新建一个空的 ASP.NET Core Web Application

然后我们通过实现接口的方式来自定义一个中间件,代码如下:

// 新建类 MyMiddleware.cs
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; namespace WebApplication1
{
public class MyMiddleware : IMiddleware
{
public Task InvokeAsync(HttpContext context, RequestDelegate next)
{
throw new NotImplementedException();
}
}
}

按照上面实现的中间件 MyMiddleware,在执行时应该会抛出 NotImplementedException.

使用接口实现的中间件需要在先在服务容器中注册

// Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; namespace WebApplication1
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 在服务容器中注册自定义中间件
services.AddSingleton<MyMiddleware>();
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} // 使用 UseMiddleware() 把自定义中间件添加到管道中
app.UseMiddleware<MyMiddleware>(); app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
}

然后 F5 启动,页面上可以看到如下结果:

符合我们上面的预期,抛出了一个 NotImplementedException.

然后我们改造下 MyMiddleware 中间件

// MyMiddleware.cs
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks; namespace WebApplication1
{
public class MyMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
// 这里不对 request 做任何处理,直接调用下一个中间件
await next(context);
}
}
}

这里相当于我们实现了一个叫做 MyMiddleware 的中间件,但是并没有对请求进行任何处理,页面上应该正常显示 Hello World! 字符串.

然后我们 F5 启动看看

嗯...符合预期.

个人觉得:这种方式最符合面向对象的特性,也符合面向接口的原则,少一些难以理解的魔法,反而有助于理解.

约定方式

编程世界有这么一句话,叫"约定大于配置".

那么编写中间件的约定是什么呢?

重新开始,新建一个空的 ASP.NET Core Web Application

然后新建一个类,类名叫做 MyMiddleware 好了,代码如下:

// MyMiddleware.cs
using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks; namespace WebApplication1
{
public class MyMiddleware
{
// 1. 需要实现一个构造函数,参数为 RequestDelegate
public MyMiddleware(RequestDelegate next)
{ } // 2. 需要实现一个叫做 InvokeAsync 方法
public async Task InvokeAsync(HttpContext context)
{
throw new NotImplementedException("这是一个按照约定方式编写的中间件,但未实现具体内容");
}
}
}

约定的内容,就是满足2个需要...不满足需要则异常.

然后我们把这个中间件,注册到管道中,以便使用

// Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; namespace WebApplication1
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
} public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} // 注册自定义中间件
// 注册顺序=1
app.UseMiddleware<MyMiddleware>(); app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}
}
}

然后 F5 启动,来看看效果

嗯,符合预期.

然后我们来调整下中间件,让请求能正常响应输出 Hello World!

using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks; namespace WebApplication1
{
public class MyMiddleware
{
private readonly RequestDelegate _next; // 需要实现一个构造函数,参数为 RequestDelegate
public MyMiddleware(RequestDelegate next)
{
_next = next;
} // 需要实现一个叫做 InvokeAsync 方法
public async Task InvokeAsync(HttpContext context)
{
// 不处理任何 request, 直接调用下一个中间件
await _next.Invoke(context);
}
}
}

然后 F5 启动,看看效果

嗯,符合预期.

个人觉得:只能说一句,约定方式是目前用的最多的方式...

End

写在最后

Tips: 有些内容可能看起来还是不太容易理解,至少当下你是很难理解的,但是套路就在哪里,好比1+1=2,你知道1+1为什么=2么?但你一定会算会用1+1=2...

ASP.NET Core 中间件的几种实现方式的更多相关文章

  1. ASP.NET Core中间件(Middleware)实现WCF SOAP服务端解析

    ASP.NET Core中间件(Middleware)进阶学习实现SOAP 解析. 本篇将介绍实现ASP.NET Core SOAP服务端解析,而不是ASP.NET Core整个WCF host. 因 ...

  2. [转]ASP.NET Core 中间件详解及项目实战

    本文转自:http://www.cnblogs.com/savorboard/p/5586229.html 前言 在上篇文章主要介绍了DotNetCore项目状况,本篇文章是我们在开发自己的项目中实际 ...

  3. 如何一秒钟从头构建一个 ASP.NET Core 中间件

    前言 其实地上本没有路,走的人多了,也便成了路. -- 鲁迅 就像上面鲁迅说的那样,其实在我们开发中间件的过程中,微软并没有制定一些策略或者文档来约束你如何编写一个中间件程序, 但是其中却存在者一些最 ...

  4. ASP.NET Core中间件实现分布式 Session

    1. ASP.NET Core中间件详解 1.1. 中间件原理 1.1.1. 什么是中间件 1.1.2. 中间件执行过程 1.1.3. 中间件的配置 1.2. 依赖注入中间件 1.3. Cookies ...

  5. ASP.NETCore学习记录(二) —— ASP.NET Core 中间件

    ASP.NET Core 中间件 目录: 什么是中间件 ? IApplicationBuilder 使用 IApplicationBuilder 创建中间件 Run.Map 与 Use 方法 实战中间 ...

  6. ASP.NET Core 中间件基本用法

    ASP.NET Core 中间件 ASP.NET Core的处理流程是一个管道,而中间件是装配到管道中的用于处理请求和响应的组件.中间件按照装配的先后顺序执行,并决定是否进入下一个组件.中间件管道的处 ...

  7. (4)ASP.NET Core 中间件

    1.前言 整个HTTP Request请求跟HTTP Response返回结果之间的处理流程是一个请求管道(request pipeline).而中间件(middleware)则是一种装配到请求管道以 ...

  8. ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 中间件 上一章节中,我们我们有讲到 Startup 类中的 Confi ...

  9. Asp.net core中间件实现原理及用法解说

    简述asp.net core中间件的实现思路 原文地址:https://www.cnblogs.com/shengyu-kmust/p/11583974.html 一次http请求的过程,就是对一个R ...

随机推荐

  1. 7-3三个模块 hashlib ,logging,configparser和序列化

    一 hashlib 主要用于字符串加密 1 import hashlib md5obj=hashlib.md5() # 实例化一个md5摘要算法的对象 md5obj.update('alex3714' ...

  2. @codechef - BIKE@ Chef and Bike

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 输入 n(n ≤ 22) 个点,m(m ≤ 8000) 个边.每 ...

  3. Jmeter正则表达式提取多个值示例

    首先了解一下常用正则表达式的语法 \d           数字 \w          数字或者字母 .             可以匹配任意字符 星号*     表示任意个字符  +       ...

  4. Java模板引擎FreeMarker介绍和使用

    http://blog.csdn.net/shimiso/article/details/8778793

  5. behavior planning——11 create a cost function speed penalty

    A  key part of getting transitions to happen when we want  them to is the design of reasonable cost ...

  6. linux中使用gbd进行单布调试

    在linux 中使用gdb命令行进行单步调试,将整个过程介绍如下: 1.在当前路径下新建文件夹main, 并进入文件夹,新建文件main.cpp mkdir main cd main touch ma ...

  7. SCSS语法格式及编译调试

    一.SASS编译 Sass 的编译有多种方法: 命令编译 GUI工具编译 自动化编译 1.1 命令编译 1)单文件编译 sass <要编译的Sass文件路径>/style.scss:< ...

  8. 2019-9-2-Visual-studio-创建项目失败vstemplate

    title author date CreateTime categories Visual studio 创建项目失败vstemplate lindexi 2019-09-02 12:57:38 + ...

  9. 不需内测账号,带你体验微信小程序完整开发过程

    不需内测账号,带你体验微信小程序完整开发过程 2016年09月24日 - 作者: SwiftCafe 微信小程序还没正式发布就已经迅速成为大家讨论的焦点,那么大家可能觉得只有收到内测邀请才能体验小程序 ...

  10. Spring Security-利用URL地址进行权限控制

    目的是:系统内存在很多不同的用户,每个用户具有不同的资源访问权限,具体表现就是某个用户对于某个URL是无权限访问的.需要Spring Security忙我们过滤. 参考:http://www.cnbl ...