mvc6中应用、服务和中间件的区别

本文关键字:中间件 区别 服务 应用 mvc6 | 更新日期: 2023-09-27 18:17:44

我试图理解MVC6中的中间件概念。对我来说还是有点模糊。我真的看不出你在Startup类中得到的几个"标准"变量之间的区别。

据我所知,有3种不同的方法告诉应用程序它应该使用特定的中间件?

你可以通过使用。但这似乎只是为了"添加"中间件?

services.AddMvc();
// Add other services
services.AddScoped<IMyCountriesRepository, MyCountriesRepository>();
services.AddScoped<IEmailer, Emailer>();

然后是IApplicationBuilder app。这是实际使用中间件加载的服务吗?所以你可以这样命名它:

app.UseMvc();
app.UseErrorPage(...);
app.UseIdentity(); // cookie authentication 

然后有一种方法来加载和使用中间件,像这样:

app.UseMiddleware<MyCustomMiddleware>();
使用中间件注册/三种类型的有什么好处?它们之间的确切区别是什么?

mvc6中应用、服务和中间件的区别

我会区分添加服务和添加中间件。

添加业务

这基本上是将特性所需的类注册到asp.net 5中构建的依赖注入容器中。(IServiceCollection接口)

你能做的最简单的事情就是手动一个一个地添加它们,如:

services.AddScoped<IMyCountriesRepository, MyCountriesRepository>();
services.AddScoped<IEmailer, Emailer>();

如果你正在构建一个更复杂的应用程序,或者一个自包含的框架,你可能想要创建一个函数来注册所需的所有服务。一个很好的方法是创建一个扩展方法:

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();

这正是services.AddMvc();正在做的。

以更灵活的方式,因为它允许你传递一个lambda来进一步自定义默认服务,如模型绑定器(如services.AddMvc(opts => opts.ModelBinders ...)),并返回一个IMvcBuilder,你可以使用它来进一步自定义它的东西,如视图引擎(如services.AddMvc().AddViewOptions(opts => opts.ViewEngines ...))。

  • 检查MvcServiceCollectionExtensionsMvcCoreServiceCollectionExtensions的执行情况
添加中间件

asp.net 5不是基于HTTP模块和处理程序,而是基于中间件的OWIN思想。Andrei 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();
});

您也可以创建自己的中间件类并注册它:

app.UseMiddleware<MyMiddleware>();

最后,您可以再次定义扩展方法来封装复杂的设置逻辑。

这就是app.UseMvc()所做的。它允许您定义路由,然后通过调用app.UseRouter()添加路由中间件。可以看到,app.UseRouter的实现通过调用builder.UseMiddleware<RouterMiddleware>(router);

RouterMiddleware添加到管道中。

您的中间件所需的任何服务先前都已注册。这意味着它们可以通过内置的DI容器提供给中间件。


最终结果是,框架使您更容易混合和匹配应用程序所需的组件(服务)和行为(中间件),只包括您需要的部分。

我想给丹尼尔的回答加上一个实际的例子。(他的回答非常详细和正确,先看看这个)。

TL;博士:

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);
});

如果您希望在各种应用程序中或由其他人共享您的中间件,您可能希望创建一个中间件并更像以下方式使用它:

app.UseMiddleware<HtmlMinifierMiddleware>(); 

将在configure方法中使用一行代码为您完成所有工作。通常的做法是发布像app.UseHtmlMinifier()这样的扩展方法,并返回可以链接用于配置或支持配置参数的特定对象。使用扩展提供了很大的灵活性、可读性和api可发现性:D

现在假设您的中间件是这样声明的:

public class HtmlMinifierMiddleware {
    public HtmlMinifier(IHtmlMinifier minifier) {
        // ...
    }
    public string Minify(string content) {
        return minifier.Minify(content);
    }
    // ...
}

如你所见,你需要传递一个IHtmlMinifer,所以你需要为DI注册它。

这是在ConfigureService上完成的,像

services.AddScoped<IHtmlMinifier, MyCoolHtmlMinifier>();

现在假设你需要的不是1个,而是很多依赖项,中间件的开发者/消费者将知道需要注册的每一个依赖项。

中间件的作者通常会附带一个扩展来方便开发者使用,比如:services.AddHtmlMinifier(),它就是这样一个扩展方法,用于将服务注册到DI容器中。

即使您没有使用中间件,您也可以使用相同的模式来利用您自己的应用程序的依赖性。

例如,如果你的应用是一个电子商务,你可以创建扩展方法来注册你的依赖项:services.AddProductManagement(), services.AddPriceCalculator(), services.AddSearching()等,或者只是services.AddMyCoolApplication(),以提供一种干净的方式来添加(注册)你的服务(依赖项),以便在你的应用的DI容器中找到。

构建管道分为两个阶段:

  • 为DI注册服务
  • 将中间件添加到管道

AddMvc注册了MVC需要的服务(例如,视图引擎,JSON格式化器等),但不向管道添加任何东西。

UseMiddleware<T>是向管道中添加中间件的通用方法。该方法将使用DI系统通过中间件类的构造函数注入依赖项。

UseMvc和类似的扩展方法使它更容易传入配置选项。如果您编写自定义中间件,则只需调用UseMiddleware<T>或提供扩展方法,这取决于您需要如何设置中间件。

您可以在这里找到更多信息:https://docs.asp.net/en/latest/fundamentals/middleware.html