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

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