OWIN и Katana. Часть 4 – Katana против "велосипедов"

Наверное многие, изучая спецификацию, уже представили какие можно создать классы для упрощения разработки. Но не стоит изобретать "велосипед". Команда проекта Katana предлагает готовые решения.

Owin.Types

С помощью NuGet добавим в проект еще одну библиотеку – Owin.Types:

PM> Install-Package Owin.Types

В ней размещаются несколько очень полезных классов. Для краткости здесь не будем перечислять все свойства и методы. Их имена достаточно понятны и в процессе разработки доступны через IntelliSense.

OwinConstants

Как уже было сказано ранее, в спецификации перечислены имена, которые являются ключами для получения объектов из словаря типа IDictionary<string, object>. Хорошей практикой является использование констант вместо строковых значений. Поэтому в Katana существует статический класс OwinConstants, в котором поля содержат текстовые значения ключей. С его помощью можно, например, строку env["owin.ResponseHeaders"] заменить на env[OwinConstants.ResponseHeaders].

OwinRequest и OwinResponse

Работать со словарем, даже используя OwinConstants, не очень удобно. Поэтому легко предположить, что многие разработчики создадут для него свои адаптеры.

Авторы Katana предусмотрели это и предлагают два класса: OwinRequest (запрос) и OwinResponse (ответ). Кроме предоставления удобного доступа к данным, второй класс содержит несколько полезных вспомогательных методов:

  • Write() – позволяет записать в ответ текстовую строку;
  • WriteAsync() – тоже самое, но асинхронно;
  • SendFileAsync() – асинхронно передает указанный файл клиенту;
  • SetHeader() – устанавливает значение для указанного заголовка.

OwinWebSocket

Еще один класс-адаптер, который представляет реализацию WebSocket для OWIN (соответствующие ключи описаны в расширении спецификации для WebSocket).

OwinHelpers

Данный класс содержит набор статических вспомогательных методов для работы с заголовками, адресами и прочими параметрами запроса или ответа. Часть их, с помощью дополнительного OwinRequestExtensions, определены как расширения класса OwinRequest.

Пример

Напишем модуль, который будет выводить текст по запросу страницы about. Но основная цель – для анализа запроса и формирования ответа использовать OwinRequest и OwinResponse.

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

    using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;

    public class AboutModule
    {
        private readonly AppFunc _next;

        public AboutModule(AppFunc next)
        {
            if (next == null)
                throw new ArgumentNullException("next");

            this._next = next;
        }

        public Task Invoke(IDictionary<string, object> env)
        {
            try {
                var request = new OwinRequest(env);
                var path = request.Path.TrimEnd(new[] { '/' });

                if (path.Equals("/About", StringComparison.OrdinalIgnoreCase)) {
                    var response = new OwinResponse(env);
                    return response.WriteAsync("About page");
                }
            }
            catch (Exception ex) {
                var tcs = new TaskCompletionSource<object>();
                tcs.SetException(ex);
                return tcs.Task;
            }

            return this._next(env);
        }
    }
}

Остается зарегистрировать модуль в классе Startup с учетом порядка вызова: после LoggerModule, но до установки варианта по умолчанию:

...
public void Configuration(IAppBuilder appBuilder)
{
    appBuilder.Use(typeof(LoggerModule), "Log Module >");
    appBuilder.Use(typeof(AboutModule));

    appBuilder.Properties["builder.DefaultApp"] = new AppFunc(
    ...

Если теперь запустить проект, то при запросе адреса /about данный модуль выведет текст "About page" .

Итак, использование классов из библиотеки Owin.Types позволяет не изобретать велосипед и делает разработку модулей более удобной. Эту тему и продолжим рассматривать дальше.


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

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