问题描述


当我们在ASP.NET Core中定义和使用中间件(Middleware)的时候,有什么好的办法可以给中间件传参数吗?

解决方案


在ASP.NET Core项目中添加一个POCO类来传递参数到中间件,例如下面的GreetingOptions类

public class GreetingOptions
{
public string GreetAt { get; set; }
public string GreetTo { get; set; }
}

然后添加一个中间件GreetingMiddleware

public class GreetingMiddleware
{
private readonly RequestDelegate next;
private readonly GreetingOptions options; public GreetingMiddleware(
RequestDelegate next,
GreetingOptions options)
{
this.next = next;
this.options = options;
} public async Task Invoke(
HttpContext context)
{
var message = $"Good {this.options.GreetAt} {this.options.GreetTo}";
await context.Response.WriteAsync(message);
}
}

解决方案A:实例类型(Instance Type)


通过添加一个扩展方法类GreetingMiddlewareExtension,来配置中间件GreetingMiddleware,并传递参数GreetingOptions options

public static class GreetingMiddlewareExtension
{
public static IApplicationBuilder UseGreeting(this IApplicationBuilder app, GreetingOptions options)
{
return app.UseMiddleware<GreetingMiddleware>(options);
}
}

在ASP.NET Core项目中Startup类的Configure方法中,启用GreetingMiddleware中间件,并传递参数到中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseGreeting(new GreetingOptions
{
GreetAt = "Morning",
GreetTo = "Tahir"
});
}

解决方案B:方法类型(Function Type)


通过添加一个扩展方法类GreetingMiddlewareExtension,来配置中间件GreetingMiddleware,并通过委托Action<GreetingOptions> configureOptions来传递参数GreetingOptions

public static class GreetingMiddlewareExtension
{
public static IApplicationBuilder UseGreeting(this IApplicationBuilder app, Action<GreetingOptions> configureOptions)
{
var options = new GreetingOptions();
configureOptions(options); return app.UseMiddleware<GreetingMiddleware>(options);
}
}

在ASP.NET Core项目中Startup类的Configure方法中,启用GreetingMiddleware中间件,并通过委托Action<GreetingOptions>传递参数到中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseGreeting(options =>
{
options.GreetAt = "Morning";
options.GreetTo = "Tahir";
});
}

讨论


前面的一篇文章中我们讨论了,定义和使用中间件(Middleware)的最好方法是,将中间件定义在一个单独的类中,然后通过扩展方法将其添加到ASP.NET Core的中间件管道(pipeline)中。

我们可以通过上面介绍的解决方案A和B,将需要传递到中间件的参数都封装为一个POCO类,并创建一个扩展方法,用下面两种方式作为扩展方法的参数:

  • POCO实例(解决方案A
  • 一个委托方法,随后通过调用该委托方法来创建并配置POCO实例(解决方案B

注意:POCO实例是通过. UseMiddleware()方法的params object[]参数来传递到中间件的构造函数中的,也就是说我们可以通过params object[]来传递任意多个参数到中间件中,只要类型和中间件的构造函数参数匹配即可。我们还可以将依赖注入参数和POCO实例参数一起定义在中间件的构造函数中,如下所示:

public class GreetingMiddleware
{
private readonly RequestDelegate next;
private readonly GreetingOptions options; //IHostingEnvironment env是依赖注入参数,GreetingOptions options是POCO实例参数
public GreetingMiddleware(RequestDelegate next, IHostingEnvironment env, GreetingOptions options)
{
string environmentName = env.EnvironmentName; this.next = next;
this.options = options;
} public async Task Invoke(
HttpContext context)
{
var message = $"Good {this.options.GreetAt} {this.options.GreetTo}";
await context.Response.WriteAsync(message);
}
}

配置依赖注入服务


前面介绍的两种解决方案同样也可以用来配置依赖注入(dependency injection)服务的容器。

为了演示,我们先添加一个POCO类MessageOptions和用到的枚举MessageFormat

public enum MessageFormat
{
None,
Upper,
Lower
} public class MessageOptions
{
public MessageFormat Format { get; set; }
}

然后添加一个依赖注入接口IMessageService,及其实现类MessageService

public interface IMessageService
{
string FormatMessage(string message);
}
public class MessageService : IMessageService
{
private readonly MessageOptions options; public MessageService(MessageOptions options)
{
this.options = options;
} public string FormatMessage(string message)
{
// use options
return this.options.Format == MessageFormat.None ? message :
this.options.Format == MessageFormat.Upper ? message.ToUpper() :
message.ToLower();
}
}

同样,接下来我们就用两种解决方案,来定义MessageService的扩展方法类MessageServiceExtension

解决方案A:实例类型(Instance Type)


public static class MessageServiceExtension
{
// Instance Type
public static IServiceCollection AddMessageFormatter(this IServiceCollection services, MessageOptions options)
{
return services.AddScoped<IMessageService>(factory =>
{
return new MessageService(options);
});
}
}

在ASP.NET Core项目中Startup类的ConfigureServices方法中,注册IMessageService和MessageService的依赖注入服务

// Instance Type
public void ConfigureServices(IServiceCollection services)
{
services.AddMessageFormatter(new MessageOptions
{
Format = MessageFormat.Lower
});
}

解决方案B:方法类型(Function Type)


public static class MessageServiceExtension
{
// Function Type
public static IServiceCollection AddMessageFormatter(this IServiceCollection services, Action<MessageOptions> configureOptions)
{
var options = new MessageOptions();
configureOptions(options); return services.AddScoped<IMessageService>(factory =>
{
return new MessageService(options);
});
}
}

在ASP.NET Core项目中Startup类的ConfigureServices方法中,注册IMessageService和MessageService的依赖注入服务

// Function Type
public void ConfigureServices(IServiceCollection services)
{
services.AddMessageFormatter(options =>
{
options.Format = MessageFormat.Lower;
});
}

本文参考自:Passing Parameters to Middleware in ASP.NET Core 2.0

如何传递参数给ASP.NET Core的中间件(Middleware)的更多相关文章

  1. ASP.NET Core 开发-中间件(Middleware)

    ASP.NET Core开发,开发并使用中间件(Middleware). 中间件是被组装成一个应用程序管道来处理请求和响应的软件组件. 每个组件选择是否传递给管道中的下一个组件的请求,并能之前和下一组 ...

  2. asp.net core mvc 中间件之WebpackDevMiddleware

    asp.net core mvc 中间件之WebpackDevMiddleware WebpackDevMiddleware中间件主要用于开发SPA应用,启用Webpack,增强网页开发体验.好吧,你 ...

  3. ASP.NET Core:中间件

    一.什么是中间件 我们都知道,任何的一个web框架都是把http请求封装成一个管道,每一次的请求都是经过管道的一系列操作,最终才会到达我们写的代码中.而中间件就是用于组成应用程序管道来处理请求和响应的 ...

  4. asp.net core mvc 中间件之路由

    asp.net core mvc 中间件之路由 路由中间件 首先看路由中间件的源码 先用httpContext实例化一个路由上下文,然后把中间件接收到的路由添加到路由上下文的路由集合 然后把路由上下文 ...

  5. 如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容?

    原文:如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容? 文章名称: 如何在ASP.NET Core自定义中间件读取Request.Body和 ...

  6. asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密。

    原文:asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密. GitHub demo https://github.com/zhanglilong23/Asp.NetCore. ...

  7. ASP.NET Core路由中间件[3]: 终结点(Endpoint)

    到目前为止,ASP.NET Core提供了两种不同的路由解决方案.传统的路由系统以IRouter对象为核心,我们姑且将其称为IRouter路由.本章介绍的是最早发布于ASP.NET Core 2.2中 ...

  8. ASP.NET Core路由中间件[2]: 路由模式

    一个Web应用本质上体现为一组终结点的集合.终结点则体现为一个暴露在网络中可供外界采用HTTP协议调用的服务,路由的作用就是建立一个请求URL模式与对应终结点之间的映射关系.借助这个映射关系,客户端可 ...

  9. ASP.NET Core之中间件

    本文翻译自:http://www.tutorialsteacher.com/core/aspnet-core-middleware 基本概念 ASP.NET Core引入了中间件的概念,中间件是在AS ...

随机推荐

  1. Django 认证

    from django.contrib import auth 1.authenticate() 提供了用户认证,即验证用户名以及密码是否正确,一般需要username和password两个关键字参数 ...

  2. node中__dirname、__filename、process.cwd()、process.chdir()表示的路径

    直接上结论:__dirname 表示当前文件所在的目录的绝对路径__filename 表示当前文件的绝对路径module.filename ==== __filename 等价process.cwd( ...

  3. aws s3文件上传设置accesskey、secretkey、sessiontoken

    背景: 最近跟进的项目会封装aws S3资源管理细节,对外提供获取文件上传凭证的API,业务方使用获取到的凭证信息直接请求aws进行文件上传.因此,测试过程需要验证S3文件上传的有效性.aws官网有提 ...

  4. sql server 2008R2无人值守批处理脚本自动化安装

    ▲版权声明:本文为博主原创文章,未经博主允许不得转载. Microsoft SQL Server 2008 R2是一款软件,提供完整的企业级技术与工具,帮助您以最低的总拥有成本获得最有价值的信息.您可 ...

  5. .NetCore Build Terminology

       .NETCore Command:    1.dotnet build 2.dotnet run 3.dotnet new classlib 4.dotnet new xunit 5.dotne ...

  6. 02LaTeX学习系列之---TeX环境的搭建

    目录 02Latex的下载与安装及其编译IDE 目录 前言 (一)Tex Live的下载 1. Tex Live官方下载网站: (二)TeXStudio 1.TeXStudio官网下载 2.TeXSt ...

  7. IDEA设置注释的颜色

    IDEA默认的灰色注释确实让人看不清,但如果把灰色调成黑色又和代码的颜色相同了,所以,不如给注释添加上绿色的背景,又护眼又容易分辨 新版本的IDEA打开Settings——Editot——Color ...

  8. break和continue语句(初学者)

    1.break语句可以从循环体内跳出循环体,即提前结束循环,接着执行循环下面的语句. 一般形式:break: break不能用于循环语句和switch语句之外的任何其他语句中. 注意:(1)break ...

  9. mysql中case的一个例子

    最近遇到一个问题: year amount num 1991 1 1.1 1991 2 1.2 1991 3 1.3 1992 1 2.1 1992 2 2.2 1992 3 3.3 把上面表格的数据 ...

  10. kuangbin fire搜索bfs

    Joe works in a maze. Unfortunately, portions of the maze have caught on fire, and the owner of the ma ...