OWIN – открытый интерфейс веб-сервера для .NET (Open Web Server Interface for .NET). Или говоря по другому – это спецификация определяющая абстакцию посредством которой взаимодействуют веб-сервер и веб-приложение. Более подробное описание спецификации можно найти на сайте owin.org, а если более конкретно, то тут. Чтобы легче было себе представить, нужно взглянуть на рисунок приведённый ниже.

Image 1

Правая диаграмма показывает общую схему структуры приложения, которое использует спецификацию OWIN для организации взаимодействия между компонентами всей инфраструктуры. Левая – схему структуры веб-приложений в Windows без использования этой спецификации, то есть то, что было раньше (есть и сейчас и будет в будущем). Если применить спецификацию OWIN к связке IIS/ASP.NET, то получится примерно следующее.

Image 2

Замечу сразу, что если быть более точным, то ни правая диаграмма первого рисунка и ни данная, в абсолютной точности не выражают схему организации структуры. Все дело в том, что нельзя просто так взять и отделить части схемы на независимые куски. Просто, на мой взгляд, для быстрого восприятия материала, они являются наиболее оптимальными для иллюстрации общей картины. Ну а дальше всё постепенно прояснится. Вернувшись к теме сразу возникает вопрос: а зачем лишний уровень абстракции и в без того перегруженный конвейер IIS/ASP.NET ? Отвечу коротко – почти незачем, просто это одна из реализаций организации работы приложения по спецификации OWIN с использованием IIS/ASP.NET. Остальные выводы будут сделаны в конце статьи. В самом начале статьи упоминалось о взаимодействии сервера и приложения, на практике, такое взаимодействие сводится к использованию функций с сигнатурой одного единственного делегата, так называемого делегата приложения. Который имеет следующий вид:

using AppFunc = Func<IDictionary<string, object>, Task>;

Входной параметр имеющий тип IDictionary<string, object> и называемый – словарь окружения, содержит все данные (переменные сервера, данные запроса и т.п.). Он не может иметь значение null, а так же быть пустым. Кроме того, должен содержать некоторые ключи определённые спецификацией. Выходной параметр имеет тип Task – инкапсулирует некоторую выполняемую задачу. На основе данного делегата строятся компонеты приложения и объединяются в цепочку, тем самым формируется конвейер обработки запросов OWIN, куда передаётся запрос на обработку. Из типа возвращаемого делегатом уже видно, что он будет работать в асинхронном режиме. Пока, всё описанное выше – это только теория. Microsft OWIN или проект под названием Katana является реализацией спецификации OWIN компанией Microsoft. Исходный код проекта полность открытый и находится на CodePlex по следующему адресу. На момент написания статьи текущая версия 3.0.0 Alpha, а RTM версия – 2.1.0. Именно последняя будет описана и использоваться в дальнейшем. Ниже представлена визуальная схема архитектуры проекта Katana, согласно спецификации OWIN.

Image 3

Если скачать и открыть проект, то можно увидеть, что примерно так всё и выглядит.

Image 4

Ниже представлены схематические изображения архитектуры веб-приложений использующих Katana и работающих по спецификации OWIN.

Image 5

И так, что же означает абреввиатура OWIN показанная на диаграммах как промежуточный слой. Это основное связующее звено в приложении, того самого промежуточного слоя, представленное в виде единственного интерфейса IAppBuilder.

namespace Owin
{
    using System;
    using System.Collections.Generic;
 
    public interface IAppBuilder
    {
        object Build(Type returnType);
        IAppBuilder New();
        IAppBuilder Use(object middleware, params object[] args);
 
        IDictionary<string, object> Properties { get; }
    }
}

Интерфейс не является частью спецификации. Тут есть очень тонкий момент: вся инфраструктура работает по спецификации OWIN, а данная абреввиатура на диаграммах, наглядно показывает просто конкретную реализацию промежуточного слоя. Теперь, чтобы лучше понять материал я покажу как создать очень простое веб-приложение, которое будет работать по спецификации OWIN. Для начала нам нужен хост, процесс в Windows в котором будет работать наше приложение. Для этого создадим простое консольное приложение в Visual Studio 2013.

Image 6

Естественно, реализация спецификации OWIN задача ресурсоёмкая, поэтому и есть проект Katana. Воспользуемся некоторыми готовыми компонентами Katana, установив их через NuGet.

Image 7

Как видно из рисунка выше, было установлено четыре сборки. Сборка OWIN, содержит один едниственный интерфейс – IAppBuilder, который был описан выше. Microsoft.Owin – содержит множество вспомагательных типов, которые облегчают создание разных компонетов Owin. Например: OwinRequest, OwinResponse, OwinContext и т.д. Сборка Microsoft.Owin.Hosting содержит типы необходимые для хостинга и запуска приложения. Ну а сборка Microsoft.Owin.Host.HttpListener содержит дефолтовый сервер OwinHttpListener проекта Katana. Это по сути обёртка вокруг стандартного System.Net.HttpListener. Для конфигурации приложения при запуске, Katana ищет класс Startup. В качестве шаблонного элемента он присутсвует в Visual Studio 2013. Добавим его. Более подробно об алгоритме поиска класса Startup написано тут.

Image8

Осталось добавить код, запускающий сервер:

using System;
using Microsoft.Owin.Hosting;
 
namespace SimpleOwinApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            const string uri = "http://localhost:8088/";
 
            using(WebApp.Start<Startup>(uri))
            {
                Console.WriteLine("Server started");
                Console.ReadKey();
                Console.WriteLine("Server stoped");
            }
        }
    }
}

и код конфигурации.

using Owin;
using Microsoft.Owin;
 
[assembly: OwinStartup(typeof(SimpleOwinApplication.Startup))]
 
namespace SimpleOwinApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Run(context =>
            {
                context.Response.ContentType = "text/html";
                return context.Response.WriteAsync(htmlText);
            });
        }
 
        private const string htmlText = "<html>" +
                                          "<head>" +
                                              "<title></title>" +
                                          "</head>" +
                                          "<body>" +
                                              "<h1>Simple Owin Application<h1>" +
                                          "</body>" +
                                        "</html>";
    }
}

Ничего особенного тут не происходит. Просто на все запросы к хосту, сервет отвечает куском кода HTML. В следующей части все детали конвейера OWIN и его компоненты будут расмотрены более детально.

Image9

Запускаем приложение, и видим что всё работает. Здесь находится ссылка на проект. Тут уже назревает вопрос: зачем нам всё это, плохо ли было без этого? Конечно нет, но если посмотреть с другой стороны, то инфраструктура веб-приложения построенная по спецификации OWIN при помощи управляемого кода даёт нам полную свободу действий и гибкость, еcли мы реализуем её без использования существующей. То есть, если мы не используем IIS/ASP.NET. Лично я не вижу смысла использовать спецификацию OWIN в приложениях IIS/ASP.NET, об этом будет ещё написано в следующих статьях. Почему не стоит? Да потому, что конвейер IIS/ASP.NET и без того перегружен. Незачем вводить ещё один дополнительный слой абстракции. И к тому же технология ASP.NET достаточно зрелая и используя накопленные возможности и опыт можно решить очень широкий круг задач, что мы и делали до сих пор и будем делать. Вывод – спецификация OWIN позволяет пересмотреть архитектуру веб-инфраструктуры не принося ничего нового в уже существующую, но позволяющая построить совершенно новую и полностью управляемую архитектуру инфраструктуры.