问题描述


当我们在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. 网络基础 Windows控制台下Ftp使用简介

    Windows控制台下Ftp使用简介 by:授客 QQ:1033553122 测试环境: ftp服务器所在主机ip:172.25.75.2 ftp用户目录:F:\ftp   C:\Users\laif ...

  2. winsock编程学习笔记

    以下部分转自博客http://blog.csdn.net/phunxm/article/details/5085869 套接字地址(sockaddr.sockaddr_in) /* * Structu ...

  3. python第三十天-类

    编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很 ...

  4. The Tomcat connector configured to listen on port 8080 failed to start. The port may already be in use or the connector may be misconfigured

    springboot 8080端口被占用报错:The Tomcat connector configured to listen on port 8080 failed to start. The p ...

  5. linux中crw brw lrw等等文件属性是什么

    今天在查看 /dev/fuse 文件的属性的时候,看到了crw_ 权限位,一时反应不过来: [root@localhost ~]# ll /dev/fuse crw-rw-rw-. root root ...

  6. sql server 无法sa登录解决办法

    大概流程:在SQL软件里面设置解决 大概流程: 打开 控制面板 -> 管理工具 -> 服务..... 详细参考地址: https://blog.csdn.net/github_351606 ...

  7. Sql注入的分类:数字型+字符型

    Sql注入: 就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.通过构造恶意的输入,使数据库执行恶意命令,造成数据泄露或者修改内容等,以 ...

  8. P1141 01迷宫 dfs连通块

    题目描述 有一个仅由数字000与111组成的n×nn \times nn×n格迷宫.若你位于一格0上,那么你可以移动到相邻444格中的某一格111上,同样若你位于一格1上,那么你可以移动到相邻444格 ...

  9. oracle 查询表中数据行(row)上最后的DML时间

    在这介绍Oracle 10G开始提供的一个伪列ORA_ROWSCN,它又分为两种模式一种是基于block这是默认的模式(块级跟踪):还有一种是基于row上,这种模式只能在建里表时指定ROWDEPEND ...

  10. MDC的使用(Mapped Diagnostic Context)的使用

    通常我们可能会有大量的任务需要提交提交到线程池执行,但是此时如果不对日志添加唯一标识进行区分的话回到错乱一坨无法进行查看.因此可以对每一天日志添加唯一的标识,例如使用userid作为日志的唯一标志.这 ...