Просмотрите или скачайте образец кода
Выполнение связующего ПО в процессе ASP.NET
Поддержка OWIN со стороны ASP.NET Core развертывается в рамках пакета
Microsoft.AspNetCore.Owin
. Чтобы импортировать поддержку OWIN в свой проект, добавьте пакет в виде зависимости в файл project.json
:"dependencies": {
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.Owin": "1.0.0"
},
Связующее ПО OWIN соответствует спецификации OWIN, которая требует использовать интерфейс
Func<IDictionary<string, object>, Task>
и настроить определенные ключи (например, owin.ResponseBody
). Ниже приведен пример связующего ПО OWIN, которое отображает текст Hello World:public Task OwinHello(IDictionary<string, object> environment)
{
string responseText = "Hello World via OWIN";
byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);
// OWIN Environment Keys: http://owin.org/spec/spec/owin-1.0.0.html
var responseStream = (Stream)environment["owin.ResponseBody"];
var responseHeaders = (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];
responseHeaders["Content-Length"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };
responseHeaders["Content-Type"] = new string[] { "text/plain" };
return responseStream.WriteAsync(responseBytes, 0, responseBytes.Length);
}
Образец подписи выдает
Task
и принимает IDictionary<string, object>
в соответствии с требованиями OWIN.В следующем коде показано, как добавить связующее ПО
OwinHello
(см. выше) в процесс ASP.NET с помощью метода расширения UseOwin
.public void Configure(IApplicationBuilder app)
{
app.UseOwin(pipeline =>
{
pipeline(next => OwinHello);
});
}
Вы можете настроить и другие действия для процесса OWIN.
Заголовки ответов следует менять только перед первой записью в поток ответов.
Не нужно выполнять много вызовов к
UseOwi
n: это снижает производительность. Компоненты OWIN работают лучше, если их объединить.app.UseOwin(pipeline =>
{
pipeline(next =>
{
// do something before
return OwinHello;
// do something after
});
});
Хостинг ASP.NET на OWIN-сервере
На OWIN-серверах можно размещать приложения ASP.NET. Один из таких серверов — Nowin, веб-сервер .NET OWIN. В пример для этой статьи мы добавили проект, который ссылается на Nowin и использует его для создания
IServer
, способного самостоятельно размещать ASP.NET Core.using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
namespace NowinSample
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseNowin()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
IServer
— это интерфейс, который требует свойство Features
и метод Start
.Start
отвечает за настройку и запуск сервера. Для этого используется серия вызовов API, настраивающих адреса, которые были проанализированы из IServerAddressesFeature. Обратите внимание: конфигурация переменной _builder
указывает, что запросы будет обрабатывать параметр appFunc
, ранее настроенный в методе. Эта функция вызывается по каждому запросу для обработки входящих запросов.Также мы добавим расширение
IWebHostBuilder
, чтобы упростить добавление и настройку сервера Nowin.using System;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.Extensions.DependencyInjection;
using Nowin;
using NowinSample;
namespace Microsoft.AspNetCore.Hosting
{
public static class NowinWebHostBuilderExtensions
{
public static IWebHostBuilder UseNowin(this IWebHostBuilder builder)
{
return builder.ConfigureServices(services =>
{
services.AddSingleton<IServer, NowinServer>();
});
}
public static IWebHostBuilder UseNowin(this IWebHostBuilder builder, Action<ServerBuilder> configure)
{
builder.ConfigureServices(services =>
{
services.Configure(configure);
});
return builder.UseNowin();
}
}
}
Затем необходимо вызвать расширение в Program.cs, чтобы выполнить приложение ASP.NET с помощью этого пользовательского сервера:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
namespace NowinSample
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseNowin()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
Подробнее о серверах ASP.NET.
Выполните ASP.NET Core на OWIN-сервере и воспользуйтесь поддержкой WebSockets
Еще один способ использовать OWIN-серверы в ASP.NET Core — получить доступ к функциям типа WebSockets. Веб-сервер .NET OWIN из предыдущего примера поддерживает встроенные веб-сокеты, которые можно использовать в приложении ASP.NET Core. В примере ниже показано простое веб-приложение, которое поддерживает веб-сокеты и возвращает отправителю все данные, отправленные на серверы через веб-сокеты.
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await EchoWebSocket(webSocket);
}
else
{
await next();
}
});
app.Run(context =>
{
return context.Response.WriteAsync("Hello World");
});
}
private async Task EchoWebSocket(WebSocket webSocket)
{
byte[] buffer = new byte[1024];
WebSocketReceiveResult received = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
while (!webSocket.CloseStatus.HasValue)
{
// Echo anything we receive
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, received.Count),
received.MessageType, received.EndOfMessage, CancellationToken.None);
received = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer),
CancellationToken.None);
}
await webSocket.CloseAsync(webSocket.CloseStatus.Value,
webSocket.CloseStatusDescription, CancellationToken.None);
}
}
Этот образец настраивается с помощью того же
NowinServer
, что и предыдущий; единственное различие заключается в способе настройки приложения в методе Configure
. Тест с помощью простого клиента веб-сокета демонстрирует приложение:Среда OWIN
Среду OWIN можно создать с помощью
HttpContext
.var environment = new OwinEnvironment(HttpContext);
var features = new OwinFeatureCollection(environment);
Ключи OWIN
Для передачи информации через обмен данными HTTP-запрос/ответ OWIN необходим объект
IDictionary<string,object>
. ASP.NET Core реализует ключи, указанные ниже. См. основную спецификацию, расширения и Основные правила работы с OWIN.Запрос данных (OWIN v1.0.0)
Ключ | Значение (тип) | Описание |
---|---|---|
owin.RequestScheme | Строка | |
owin.RequestMethod | Строка | |
owin.RequestPathBase | Строка | |
owin.RequestPath | Строка | |
owin.RequestQueryString | Строка | |
owin.RequestProtocol | Строка | |
owin.RequestHeaders | IDictionary<string,string[]> | |
owin.RequestBody | Поток |
Запрос данных (OWIN v1.1.0)
Ключ | Значение (тип) | Описание |
---|---|---|
owin.RequestId | Строка | Необязательно |
Ответные данные (OWIN v1.0.0)
Ключ | Значение (тип) | Описание |
---|---|---|
owin.ResponseStatusCode | int | Необязательно |
owin.ResponseReasonPhrase | Строка | Необязательно |
owin.ResponseHeaders | IDictionary<string,string[]> | |
owin.ResponseBody | Поток |
Другие данные (OWIN v1.0.0)
Ключ | Значение (тип) | Описание |
---|---|---|
owin.CallCancelled | CancellationToken | |
owin.Version | Строка |
Общие ключи
Ключ | Значение (тип) | Описание |
---|---|---|
ssl.ClientCertificate | X509Certificate | |
ssl.LoadClientCertAsync | FuncTask | |
server.RemoteIpAddress | Строка | |
server.RemotePort | Строка | |
server.LocalIpAddress | Строка | |
server.LocalPort | Строка | |
server.IsLocal | bool | |
server.OnSendingHeaders | ActionActionobject,object |
SendFiles v0.3.0
Ключ | Значение (тип) | Описание |
---|---|---|
sendfile.SendAsync | См. Передача подписи | По запросу |
Opaque v0.3.0
Ключ | Значение (тип) | Описание |
---|---|---|
opaque.Version | Строка | |
opaque.Upgrade | OpaqueUpgrade | См. Передача подписи |
opaque.Stream | Поток | |
opaque.CallCancelled | CancellationToken |
WebSocket v0.3.0
Ключ | Значение (тип) | Описание |
---|---|---|
websocket.Version | Строка | |
websocket.Accept | WebSocketAccept | См. Передача подписи |
websocket.AcceptAlt | Не указано | |
websocket.SubProtocol | Строка | См. шаг 5.5 в Разделе 4.2.2 RFC6455 |
websocket.SendAsync | WebSocketSendAsync | См. Передача подписи |
websocket.ReceiveAsync | WebSocketReceiveAsync | См. Передача подписи |
websocket.CloseAsync | WebSocketCloseAsync | См. Передача подписи |
websocket.CallCancelled | CancellationToken | |
websocket.ClientCloseStatus | int | Необязательно |
websocket.ClientCloseDescription | Строка | Необязательно |
Дополнительные ресурсы
Комментарии (9)
unsafePtr
06.12.2017 15:34+1Что интересно, по факту есть всего несколько имплементаций под OWIN интерфейс а именно Kestrel и Katana(IIS). Может кто знает проекты или попытки написать свой сервер под OWIN?
stepank
06.12.2017 15:57+2Katana — это не только IIS, есть ещё self host вариант, пакет Microsoft.Owin.SelfHost
TakinosaJi
06.12.2017 18:33Зачем использовать OWIN как middleware с Core, когда ASP.NET Core и есть middleware?
caballero
07.12.2017 04:58Проект OWIN проще переносить со стандартного фреймворка на Core и наоборот Другое дело — зачем в Core вообще изобретали своe middleware a не взяли за основу OWIN и не путали людей похожими интерфейсами.
dotnetdonik
10.12.2017 12:51Что бы развивать asp.net core быстрее чем стандарт. Owin это просто интерфейс/адаптер, через которые можно подключать больше компонентов совместимых с owin спецификацией. Middleware это просто ещё один способ обозвать всем известный паттерн chain of responsibility, он был и до появления owin — в веб формах, классическом mvc(http modules), в web api — message handlers/delegating handlers.
kefirr
07.12.2017 00:07project.json
Это мёртвый механизм, зачем его упоминать? От него отказались в пользу
csproj
:
https://stackoverflow.com/questions/38536978/is-project-json-deprecated
https://docs.microsoft.com/en-us/dotnet/core/tools/project-json-to-csproj
RomanGL
Это законно, делать что-то в методе после return? Кажется, у вас ошибочка.
RouR
Скорее всего речь о том, что потом будет выполнен следующий пайплайн, в котором будет «do something after»
uterr
этот кусок кода создает анонимную функцию и передает ее как параметр в функцию pipeline, а не вызывает тело функции