Разница между приложением, сервисами и промежуточным программным обеспечением в mvc6

Я пытаюсь понять концепцию промежуточного программного обеспечения в 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>();

В чем преимущество трех типов регистрации/использования промежуточного программного обеспечения? Каковы точные различия между ними?

Ответы

Ответ 1

Я бы различал добавление сервисов и добавление промежуточного программного обеспечения.

Добавление служб

Это в основном регистрация классов, необходимых вашей функции, в контейнер инъекций зависимостей, построенный в 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, вы можете использовать для дальнейшей настройки таких вещей, как движки просмотра (Like services.AddMvc().AddViewOptions(opts => opts.ViewEngines ...)).

Добавление промежуточного программного обеспечения

ASP.Net 5 не основан на HTTP-модулях и обработчиках и вместо этого основан на идее промежуточного программного обеспечения OWIN. Существует [хорошая запись в блоге] (http://dzimchuk.net/post/understanding-aspnet-5-middleware) Andrei Dzimchuk, описывающая промежуточное программное обеспечение, которое прекрасно суммирует его:

Middleware. Проход через компоненты, которые образуют конвейер между сервером и приложением для проверки, маршрутизации или изменения сообщений запроса и ответа для определенной цели.

И это определение относится и к ASP.NET 5. Среднее ПО можно рассматривать как HTTP-модули и обработчики, которые мы использовали в классическом ASP.NET. Некоторое промежуточное программное обеспечение будет выполнять различные промежуточные задачи при обработке запросов, таких как аутентификация, извлечение и сохранение состояния сеанса, ведение журнала и т.д. Некоторые из них будут конечными обработчиками запросов, которые будут давать ответы.

Итак, теперь вы хотите добавить свое собственное поведение в конвейер 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 добавляет RouterMiddleware в конвейер с вызовом builder.UseMiddleware<RouterMiddleware>(router);

Любые службы, необходимые вашему промежуточному программному обеспечению, ранее были зарегистрированы. Это означает, что они будут доступны для вашего промежуточного программного обеспечения через встроенный контейнер DI.


Конечный результат заключается в том, что структура упрощает вам в основном смешивать и сопоставлять компоненты (службы) и поведение (промежуточное ПО), необходимые вашему приложению, включая только те биты, которые вам нужны.

Ответ 2

Я хотел бы добавить к Даниэлю ответ на практический пример. (его ответ очень подробный и правильный, сначала проверьте это).

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 для вашего приложения.

Ответ 3

Существует два этапа построения трубопровода:

  • Регистрация служб для DI
  • Добавление промежуточного программного обеспечения в конвейер

AddMvc регистрирует службы, которые нужны MVC (например, механизм просмотра, форматировщик JSON и т.д.), но ничего не добавляет к конвейеру.

UseMiddleware<T> - это общий метод для добавления промежуточного программного обеспечения в конвейер. Этот метод будет использовать систему DI для выполнения зависимостей инъекций через конструктор класса промежуточного программного обеспечения.

UseMvc и т.п. - методы расширения, которые упрощают передачу параметров конфигурации. Если вы пишете специальное промежуточное программное обеспечение, вы можете просто вызвать UseMiddleware<T> или предоставить метод расширения, в зависимости от того, как вам нужно настроить промежуточное программное обеспечение.

Вы можете найти более подробную информацию здесь: https://docs.asp.net/en/latest/fundamentals/middleware.html