Что такое Owin и проект Katana

Исторически Microsoft развивала 2 направления веб разработки. Это классический ASP и альтернатива ему (тогда еще молодой) ASP.NET. Классический ASP в то время (мы говорим о 2000 годах) был одной из основных технологий для создания веб сайтов. Java также была популярна для программирования в вебе. ASP как и php мешал разметку и бизнес логику. Но уже использование этой технологии позволило разработчикам абстрагироваться от базового HTTP и заняться дополнительными функциями, такими как сессия и кеширование. Разработка больших приложений приводила к разбуханию и дублированию кода.

asp.netASP.NET был призван организовать генерацию разметки и бизнел логику в разных местах. Он был похож на WinForms разработку, тогда еще и VB6. ASP.NET и сейчас является своего рода Web Forms и использует понятие компонент, state и серверную обработку html кнопок.

Существовало несколько проблем при использовании технологии ASP.NET. Первая, это то, что компоненты веб приложения были сильно связаны между собой. Обязательным условием была ссылка на библиотеку System.Web.dll. Которая в свою очередь требовала Internet Information Services (IIS) для работы. Второй проблемой была завязка ASP.NET на .NET. Что означает периодичность выпусков версий раз в несколько лет. Разработчикам хочется использовать современный софт при разработке.

Открытый веб интерфейс для .NET

Open Web Interface for .NET (OWIN). Команда разработчиков .NET вдохновилась в сообществе Ruby на создание абстракции между веб серверами и компонентами приложения. OWIN это прежде всего спецификация. При разработки были обозначены 2 цели:

Схема OWIN с сайта byterot.blogspot.ru показана ниже. 

Схема работы OWIN

В результате работы абстракция OWIN состоит из 2 компонент. Первый это словарь окружающей среды. Этот словарь содержит все настройки обработки HTTP запросов.  Словарь определен следующим образом

IDictionary<string, object>

В дополнение спецификация OWIN определяет основные пары ключ-значение для словаря.

Ключ Описание значения
owin.RequestBody Stream с телом запроса (если таковой имеется).  Может быть null.
owin.RequestHeaders Заголовки запроса, представлены в виде IDictionary<string, string[]>.
owin.RequestMethod Строка, содержащая метод запроса (например "GET" или "POST")
owin.RequestPath Строка, содержащая путь запроса.
owin.RequestProtocol Строка, содержащая информацию о названии и версии протокола (например "HTTP/1.0" или "HTTP/1.1").
owin.RequestQueryString Строка, содержащая параметры запроса. Может быть пустой. Не включает знак "?"
owin.RequestScheme Строка, с типом соединения (http или https)

Второй ключевой компонент OWIN это делегат приложения. Эта функция служит основным интерфейсом между всеми компонентами в приложении OWIN.

Func<IDictionary<string, object>, Task>;

Сборка nuget Owin.dll содержит определение единственного интерфейса IAppBuilder, формально определен в 4-й секции спецификаии OWIN. Формально он определен так:

// Assembly: Owin, Version=1.0.0.0
// Runtime: 4.0
// Architecture: I386
using System;
using System.Collections.Generic;
namespace Owin
{
        public interface IAppBuilder
        {
                IDictionary<string, object> Properties
                {
                        get;
                }
                IAppBuilder Use(object middleware, params object[] args);
                object Build(Type returnType);
                IAppBuilder New();
        }

}

Проект Katana

В то время как owin.dll является творением сообщества, проект с открытым исходным кодом Katana представляет собой набор компонентов OWIN, разработанных и опубликованных Microsoft. Эти компоненты включают в себя компоненты инфраструктуры (хосты и серверы), а также функциональным компоненты, такие как модули авторизации, аутентификации и привязанные к платформе SignalR и Asp.Net Web API.

Разработка Katana преследовала 3 основные цели:

Рассмотрим на примере процесс создания проекта по спецификации OWIN.

Для начала создаем пустой ASP.NET MVC 5 проект. OWIN отделяет нас от реализации сервера. Хотя изначально Visual Studio 2013 создает проект где есть файл Startup.cs и файл Global.asax. Следует полностью удалить файл Global.asax для работы по спецификации OWIN.

В файле Startup.cs определить атрибут [assembly: OwinStartup(typeof(Startup))].

И описать единственный метод настройки приложения. Для пример рассмотрим сайт и веб api на одном уровне и домене.

public void Configuration(IAppBuilder app)
{
    //Конфигурация ASP.NET Idenitity Framework
    //Будет рассмотрен в следующих статьях
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);


    //Указываем, что запросы, начинающиеся на "/api" 
    //следует обрабатывать таким образом
    app.Map("/api", inner =>
    {
        //Используем аутентификацию с помощью токенов
        inner.UseOAuthBearerTokens(WebApiConfig.OAuthServerOptions);

        //Регистрируем роутинг
        HttpConfiguration config = new HttpConfiguration();
        WebApiConfig.Register(config);
        inner.UseWebApi(config);
    });



    //Конфигурация перенесена из Global.asax
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    ConfigureAuth.Configure(app);
}

Удобно реализовывать контроллеры. В примере они выглядят так:

Пример контроллеров в OWIN Katana проекте

Настройка авторизации выглядит следующим образом

public class ConfigureAuth
{
    public static void Configure(IAppBuilder app)
    {
        // Используем авторизацию с помощью Cookies
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/account/login"),
            Provider = new CookieAuthenticationProvider
            {
                //New code 
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser, int>
                    (
                         validateInterval: TimeSpan.FromMinutes(30),
                         regenerateIdentityCallback: (manager, user) => user.GenerateUserIdentityAsync(manager),
                         getUserIdCallback: (id) => (Int32.Parse(id.GetUserId()))
                    ),

            },
            CookieName = "mysite-cookie-name"

        });
    }
}

В отличии от стандартного ASP.NET MVC больше можно не объявлять machine key в соответствующей секции web.config, чтобы cookies правильно шифровались и расшифровывались. Все это делает Katana.

Хотя OWIN и Katana призваны оградить нас от целевой платформы и сделать разработку веб приложений компонентной, это требует подключения большого количества пакетов nuget. Вот пример одного не сложного приложения.

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Antlr" version="3.4.1.9004" targetFramework="net451" />
  <package id="CommonServiceLocator" version="1.3" targetFramework="net451" />
  <package id="EntityFramework" version="6.1.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.Identity.Core" version="2.0.1" targetFramework="net451" />
  <package id="Microsoft.AspNet.Identity.Core.ru" version="2.0.1" targetFramework="net451" />
  <package id="Microsoft.AspNet.Identity.EntityFramework" version="2.0.1" targetFramework="net451" />
  <package id="Microsoft.AspNet.Identity.Owin" version="2.0.1" targetFramework="net451" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.Razor" version="3.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.0" targetFramework="net451" />
  <package id="Microsoft.Owin" version="2.1.0" targetFramework="net451" />
  <package id="Microsoft.Owin.Host.HttpListener" version="2.1.0" targetFramework="net451" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="2.1.0" targetFramework="net451" />
  <package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net451" />
  <package id="Microsoft.Owin.Security" version="2.1.0" targetFramework="net451" />
  <package id="Microsoft.Owin.Security.Cookies" version="2.1.0" targetFramework="net451" />
  <package id="Microsoft.Owin.Security.OAuth" version="2.1.0" targetFramework="net451" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net451" />
  <package id="Newtonsoft.Json" version="6.0.3" targetFramework="net451" />
  <package id="Owin" version="1.0" targetFramework="net451" />
  <package id="structuremap" version="3.0.0.108" targetFramework="net451" />
  <package id="StructureMap.MVC5" version="3.0.4.125" targetFramework="net451" />
  <package id="structuremap.web" version="3.0.0.108" targetFramework="net451" />
  <package id="WebActivatorEx" version="2.0.5" targetFramework="net451" />
  <package id="WebGrease" version="1.6.0" targetFramework="net451" />
</packages>

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

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

Почти каждый пакет в проекте Катана зависит, прямо или косвенно, от Owin. Это тот пакет, который содержит интерфейс IAppBuilder. Он обеспечивает конкретную реализацию последовательности запуска приложения, описанного в разделе 4 спецификации Owin. Кроме того, многие из пакетов зависят от Microsoft.Owin, который обеспечивает набор вспомогательных классов для работы с HTTP.

Для того, чтобы запустить OWIN проект на базе сервера IIS нужно использовать пакет OwinHost и пакет Microsoft.Owin.Hosting для использования в качестве хостинга любое приложение (например консольное приложение).

Комментарии

comments powered by Disqus