Viv*_*ndi 19 c# middleware asp.net-core-mvc
我试图理解MVC6中的中间件概念.它对我来说仍然含糊不清.我没有真正看到你在Startup
课堂上得到的一些"标准"变量之间的差异.
据我所知,有三种不同的方法告诉应用程序它应该使用特定的中间件?
您可以使用服务调用中间件.但这似乎只是为了"添加"中间件?
services.AddMvc();
// Add other services
services.AddScoped<IMyCountriesRepository, MyCountriesRepository>();
services.AddScoped<IEmailer, Emailer>();
Run Code Online (Sandbox Code Playgroud)
那你有IApplicationBuilder app
.这是实际使用服务中加载的中间件吗?所以你可以这样称呼:
app.UseMvc();
app.UseErrorPage(...);
app.UseIdentity(); // cookie authentication
Run Code Online (Sandbox Code Playgroud)
然后有一种方法来加载和使用这样的中间件:
app.UseMiddleware<MyCustomMiddleware>();
Run Code Online (Sandbox Code Playgroud)
有三种类型的注册/使用中间件有什么好处?它们之间的确切差异是什么?
Dan*_*.G. 16
我会区分添加服务和添加中间件.
添加服务
这基本上是将您的功能所需的类注册到ASP .Net 5中构建的依赖注入容器中.(IServiceCollection
接口)
您可以做的最简单的事情是逐个手动添加它们,如下所示:
services.AddScoped<IMyCountriesRepository, MyCountriesRepository>();
services.AddScoped<IEmailer, Emailer>();
Run Code Online (Sandbox Code Playgroud)
如果要构建更复杂的应用程序或自包含框架,则可能需要创建一个注册所需服务的函数.这样做的好方法是创建一个扩展方法:
public static void AddMyServices(this IServiceCollection services)
{
services.AddScoped<IMyCountriesRepository, MyCountriesRepository>();
services.AddScoped<IEmailer, Emailer>();
...
}
//register all your services just by running the ext method:
services.AddMyServices();
Run Code Online (Sandbox Code Playgroud)
这正是services.AddMvc();
在做什么.
以更灵活的方式,它允许您传递lambda以进一步自定义默认服务,如模型绑定器(Like
services.AddMvc(opts => opts.ModelBinders ...)
),并返回一个IMvcBuilder,您可以使用它来进一步自定义它,如视图引擎(Likeservices.AddMvc().AddViewOptions(opts => opts.ViewEngines ...)
).
添加中间件
ASP .Net 5不是基于HTTP模块和处理程序,而是基于OWIN中间件的概念.有一个不错的博客条目由 安德烈Dzimchuk描述这很好地概括了它的中间件:
中间件 - 通过构成服务器和应用程序之间管道的组件来检查,路由或修改特定目的的请求和响应消息.
此定义也适用于ASP.NET 5.中间件可以被认为是我们在经典ASP.NET中拥有的HTTP模块和处理程序.一些中间件在处理诸如认证,会话状态检索和持久性,日志记录等请求时将实现各种中间任务.其中一些将是产生响应的最终请求处理程序.
所以现在你想将自己的行为添加到ASP管道中.
最简单的事情是定义内联中间件:
app.Use(async (context, next) =>
{
//do something before passing the request to the next middleware
await next.Invoke();
});
Run Code Online (Sandbox Code Playgroud)
您还可以创建自己的中间件类并注册它:
app.UseMiddleware<MyMiddleware>();
Run Code Online (Sandbox Code Playgroud)
最后,您可以再次定义扩展方法以封装复杂的设置逻辑.
这是做什么的
app.UseMvc()
.它允许您定义路由,然后通过调用添加路由中间件app.UseRouter()
.正如您所看到的,执行app.UseRouter
将RouterMiddleware
调用添加到管道中builder.UseMiddleware<RouterMiddleware>(router);
您的中间件所需的任何服务以前都已注册.这意味着它们将通过内置的DI容器提供给中间件.
最终结果是,框架使您更容易基本混合和匹配应用程序所需的组件(服务)和行为(中间件),包括您需要的位.
我想在丹尼尔回答一个实际的例子.(他的答案非常详细和正确,请先检查一下).
TL; DR:
services.Add
与中间件没有直接关系.它是关于在依赖注入容器中注册依赖项.
app.Use
樱桃选择哪个代码将在管道中运行(做逻辑),按顺序,如果允许管道继续处理.想象力是这里的限制,一个例子是编写一个中间件,根据IP地址,你可以显示一个页面,上面写着:"你所在的国家/地区不提供抱歉服务"
app.UseMiddleware
它是相同的,app.Use
但不是声明代码内联,而是指定一个将具有将为您调用的Invoke方法的类.
现在,我们来看一些示例代码:
假设您希望应用程序处理输出或某些输出,例如缩小HTML.
您可以添加一个中间件来拦截响应,然后再将其写入输出并缩小它.
所以你可以使用:
app.Use(async (context, next) =>
{
await next(context);
context.Response // will have the response as processed by all the previous middleswares like mvc.
if IsMinifiable(context.Response)
MinifyResponse(context.Response);
});
Run Code Online (Sandbox Code Playgroud)
如果您想在各种应用程序或其他人共享中间件,您可能需要创建一个中间件并使用它更像:
app.UseMiddleware<HtmlMinifierMiddleware>();
Run Code Online (Sandbox Code Playgroud)
这将通过configure方法中的单行代码为您完成所有工作.通常的做法是发布扩展方法,app.UseHtmlMinifier()
并返回可以链接以进行配置或支持配置参数的特定对象.使用扩展提供了很多灵活性,可读性和api可发现性:D
现在想象你的中间件是这样的:
public class HtmlMinifierMiddleware {
public HtmlMinifier(IHtmlMinifier minifier) {
// ...
}
public string Minify(string content) {
return minifier.Minify(content);
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
如您所见,您需要传递IHtmlMinifer,因此您需要为DI注册它.
这在ConfigureService上完成,如:
services.AddScoped<IHtmlMinifier, MyCoolHtmlMinifier>();
Run Code Online (Sandbox Code Playgroud)
现在假设您不需要1,但需要很多依赖项,中间件的开发人员/使用者需要知道需要注册的每个依赖项.
中间件的作者通常会附带一个扩展来简化开发人员的使用,例如:services.AddHtmlMinifier()
这就是注册服务进入DI容器的扩展方法.
即使您没有使用中间件,也可以使用相同的模式利用自己应用程序的依赖关系.
例如,如果您的应用程序是一个电子商务,您可以创建注册你的依赖扩展方法:services.AddProductManagement()
,services.AddPriceCalculator()
,services.AddSearching()
,等,或只services.AddMyCoolApplication()
提供添加(注册)您的服务(依赖)的清洁方式由DI容器的发现你的申请.