OWIN и Katana. Часть 4.1 – Улучшенная настройка модулей

Katana не только предлагает адаптеры и вспомогательные классы. Она также расширяет возможности по декларации модулей в Startup. Это позволяет избежать написания еще ряда "велосипедов".

Owin.Extensions

В первую очередь необходимо установить библиотеку Owin.Extensions. Для этого, как и раньше, воспользуемся консолью NuGet и введем команду:

PM> Install-Package Owin.Extensions

Внутри Owin.Extensions.dll находится всего один статический класс – StartupExtensions. Его методы являются расширениями интерфейса IAppBuilder. Рассмотрим их:

Func<IDictionary<string, object>, Task> BuildNew(Action<IAppBuilder> configuration)

– c помощью отдельного экземпляра IAppBuilder генерирует итоговый обработчик на основе переданной конфигурации configuration. Это позволяет создавать дополнительные независимые конвейера, которые можно использовать как ветки в работе основного.

Таким образом, появляется возможность оперировать не отдельными модулями, а целыми их блоками. Например, основной конвейер содержит только определенную базовую логику и ведет журнал, а для разных запросов подключаются различные дополнительные ветки.

UseFunc(…)

– задает функцию, которая возвращает AppFunc для обработки запроса. В качестве параметров используются до 4 значений любого типа и следующий в цепочке обработчик AppFunc.

UseFunc(this IAppBuilder builder, Func<AppFunc, AppFunc> middleware)

UseFunc<T1>(this IAppBuilder builder, Func<AppFunc, T1, AppFunc> middleware, T1 arg1)
UseFunc<T1, T2>(this IAppBuilder builder, Func<AppFunc, T1, T2, AppFunc> middleware, T1 arg1, T2 arg2)
UseFunc<T1, T2, T3>(this IAppBuilder builder, Func<AppFunc, T1, T2, T3, AppFunc> middleware, T1 arg1, T2 arg2, T3 arg3)
UseFunc<T1, T2, T3, T4>(this IAppBuilder builder, Func<AppFunc, T1, T2, T3, T4, AppFunc> middleware, T1 arg1, T2 arg2, T3 arg3, T4 arg4)

UseFunc<T1>(this IAppBuilder builder, Func<T1, Func<AppFunc, AppFunc>> middleware, T1 arg1)
UseFunc<T1, T2>(this IAppBuilder builder, Func<T1, T2, Func<AppFunc, AppFunc>> middleware, T1 arg1, T2 arg2)
UseFunc<T1, T2, T3>(this IAppBuilder builder, Func<T1, T2, T3, Func<AppFunc, AppFunc>> middleware, T1 arg1, T2 arg2, T3 arg3)
UseFunc<T1, T2, T3, T4>(this IAppBuilder builder, Func<T1, T2, T3, T4, Func<AppFunc, AppFunc>> middleware, T1 arg1, T2 arg2, T3 arg3, T4 arg4)

Такие функции хорошо подходят для выбора нужных дополнительных веток конвейера или отдельных модулей согласно определенной логики.

UseFilter(…)

– добавляет в цепочку конвейера фильтры. Это методы, которые соответствуют одному из типов:

  • delegate void OwinFilter(OwinRequest request);
  • delegate Task OwinFilterAsync(OwinRequest request);

Как можно заметить, они получают доступ только к исходному запросу. В случае успешного завершения работы, его обработка всегда продолжается.

UseHandler(…)

– устанавливает обработчик, получающий в качестве параметров OwinRequest и OwinResponse. Его поведение зависит от его же типа:

  • delegate void OwinHandler(OwinRequest request, OwinResponse response) – завершает обработку. В случае ошибки может выкинуть исключение.
  • delegate Task OwinHandlerAsync(OwinRequest request, OwinResponse response) – возвращает Task, представляющий асинхронную задачу или её результат. При этом обработка завершается.
  • delegate Task OwinHandlerChained(OwinRequest request, OwinResponse response, Func<Task> next) – аналогичен предыдущему, но получает функцию next, которая является следующим обработчиком в цепочке конвейера, и может передать запрос дальше.

Пример

Посмотрим на использование UseHandler и, для примера, добавим вывод текста главной страницы (по з��просу "/"). На роль обработчика здесь подходит OwinHandlerChained. Данный тип обработчика выбран потому, что при запросе страницы, отличной от главной, необходимо передать обработку дальше.

Создадим класс HomePageModule. Для упрощения он будет статический. Сигнатура его единственного метода ShowMainPage() будет соответствовать выбранному типу обработчика:

namespace OwinDemo
{
    using System;
    using System.Threading.Tasks;
    using Owin.Types;

    public class HomePageModule
    {
        public static Task ShowMainPage(OwinRequest request, OwinResponse response, Func<Task> next)
        {
            try {
                if (request.Path.Equals("/", StringComparison.OrdinalIgnoreCase))
                    return response.WriteAsync("Home page");
            }
            catch (Exception ex) {
                var tcs = new TaskCompletionSource<object>();
                tcs.SetException(ex);
                return tcs.Task;
            }

            return next();
        }
    }
}

Остается только зарегистрировать обработчик в методе Configuration():

...
appBuilder.Use(typeof(LoggerModule), "Log Module >");
appBuilder.UseHandler(HomePageModule.ShowMainPage);
appBuilder.Use(typeof(AboutModule));
...

Теперь можно запустить проект и проверить работоспособность всех модулей.

В следующей части рассмотрим главную особенность OWIN – независимость от серверной платформы.


Исходный код проекта (C#, Visual Studio 2012): OwinDemo-part4-1.zip

Добавить комментарий