ASP.NET Coreの準備:OWINとKatanaについて詳しく説明します

ASP.NET Coreプラットフォーム(以前のASP.NET 5)に関する一連の記事の中で、別の記事を共有できることを嬉しく思います。 今回は、Radarioの.NET開発者であるVyacheslav Bobikが、OWIN、Katanaテクノロジーの使用、および関連する問題についての話で、プラットフォームに関する話を続けます。 サイクルのすべての記事はここでいつでも見つけることができます#aspnetcolumn -Vladimir Yunev

ちょっとした歴史


ASP.NET MVCバージョンのCTPが発売されたばかりの遠い日には、クロスプラットフォーム性については誰も考えていませんでした。および別のOS上。
時間が経つにつれて、ASP.NET MVCフレームワークの富が拡大し、モノリシックなSystem.Webライブラリが拡大しました。このライブラリは、フレームワークが依存し、その複雑さが増しました。 ある時点で、つまり第4バージョンでは、このフレームワークは非常に大きくなり、IISにほぼ固定されました。

一方、ASP.NET Web APIがありました。これは、IISイベントモデルに直接依存せず、IISなしで独立してホストできました(自己ホスト)。 ある時点で、Microsoftのスタッフは、.Netで書かれたWebアプリケーションをIISだけでなく他のWebサーバーでも実行でき、処理プロセスに柔軟に統合できる機能を提供する機器が必要であることを理解しましたクエリ。 その結果、OWIN仕様とKatanaプロジェクトが登場しました。

OWINの使用を開始する


Katanaは、抽象化をホストするためのWebアプリケーションを作成および実行するためのコンポーネントのセットです。 ホスティングの抽象化はOWINです。 OWINのメインインターフェイスは、 アプリケーションデリゲートまたはAppFuncと呼ばれます

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

各OWINアプリケーションには、コンポーネントの定義が配置されるStartupクラスが必要です。 このようなクラスの検出をアプリケーションに報告する方法はいくつかあります。

1つ目は、IAppBuilderを受け入れるConfigurationメソッドを使用して、アプリケーションにStartupクラスを作成することです。

 public class Startup { public void Configuration(IAppBuilder app) { app.Use(...); app.Use(...); } } 

これらのapp.Use(..)の呼び出しにより、パイプライン処理プロセスを柔軟に構成できます。

2番目は、特別な属性でマークすることです。

 [assembly: OwinStartup(typeof(App.TestApp))] 

ASP.NET Coreでは、OWINサポートはKatanaプロジェクトに基づいており、変更および追加が行われています。 そのため、 IAppBuilderは IApplicationBuilderに置き換えられましたが、Katanaで作業した場合は、OWINモジュールを簡単に作成できます。

世界中で通例のように、単純なHello Worldモジュールを作成しましょう。 空のASP.NET Coreプロジェクトを作成します。 Startupクラスは次のようになります。

 public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { // Add the platform handler to the request pipeline. app.UseIISPlatformHandler(); app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } } 

クラスが少し違って見える場合でも大丈夫です。ASP.NET5 beta-8を使用した例では( この記事を書いている時点での現在のバージョンはVUです )、Startupの初期バージョンでは少し異なっています。 nugetパッケージMicrosoft.AspNet.Owinもインストールします。 これを行うには、project.jsonに移動し、依存関係セクションに挿入します。

 Microsoft.AspNet.Owin" : "1.0.0-beta8" 

例として、小さなメソッドを作成します。

 public Task OwinHello(IDictionary<string, object> enviroment) { var responseText = "Hello via Owin"; var responseBytes = Encoding.UTF8.GetBytes(responseText); var responseStream = (Stream)enviroment["owin.ResponseBody"]; var responseHeaders = (IDictionary<string, string[]>)enviroment["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); } 

OwinHelloメソッドの呼び出しをConfigureメソッドに追加します。

 app.UseOwin(pipeline => pipeline(next => OwinHello)); 

これで、Startupクラスは次のようになります。

 public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { // Add the platform handler to the request pipeline. app.UseIISPlatformHandler(); app.UseOwin(pipeline => pipeline(next => OwinHello)); app.Run(async (context) => { await context.Response.WriteAsync("Hello World"); }); } public Task OwinHello(IDictionary<string, object> enviroment) { var responseText = "Hello Owin"; var responseBytes = Encoding.UTF8.GetBytes(responseText); var responseStream = (Stream)enviroment["owin.ResponseBody"]; var responseHeaders = (IDictionary<string, string[]>)enviroment["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); } } 

ここでプロジェクトを開始すると、ブラウザに「Hello Owin」が表示されます。 読者は「Hellow OwinがHello Worldなしで表示されたのはなぜですか」と尋ねるかもしれません。 これは、 仕様によると、ヘッダー、コードのステータス、リクエスト本文などの変更は、リクエスト本文(レスポンス本文ストリーム)への最初の書き込みまでし​​か可能でないためです。

リクエストの内部にアクセスするには、キーowin.ResponseBodyowin.ResponseHeaders使用するだけowin.ResponseHeaders 。 また、 仕様でキーの全セットを見ることができます。 リクエストの実行を整理しましたが、owinを使用するための2つの異なるメソッドRunUseありUse 。これらは一見同じことをします。 これは完全に真実ではありません。

Run合意では、 middlewareをリクエスト処理の最後(パイプライン)に追加する場合にのみこのメソッドを使用する価値があると説明されているため、 Run後は何も呼び出されません。

ここで、より複雑なもの、たとえば単純な基本認証を備えたコンポーネントを作成しましょう。 詳細については、ASP.NETチームの皆さん 最高の 複雑な場合は、 middleware別個のクラスmiddleware配置し、そのコンポーネントを拡張メソッドとして呼び出すことをお勧めします。

単一のInvokeメソッドでBasicAuthMiddlewareクラスを作成します

 //     production public class BasicAuthMiddleware { private readonly RequestDelegate _next; public BasicAuthMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { if (context.Request.Headers["Authorization"] == "Basic aGFicmE6aGFicg==") { context.Response.StatusCode = 200; await _next.Invoke(context); } else { context.Response.StatusCode = 401; context.Response.Headers.Add("WWW-Authenticate", "Basic realm=\"localhost\""); } } } 

それでは、簡単な拡張メソッドを書きましょう。 BasicAuthMiddlewareExtensionクラスを作成します

 public static class BasicAuthMiddlewareExtension { public static IApplicationBuilder UseBasicAuth(this IApplicationBuilder builder) { return builder.UseMiddleware<BasicAuthMiddleware>(); } } 

Startupクラスでコンポーネントを接続します。

 public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { app.UseIISPlatformHandler(); app.UseBasicAuth(); app.Run(async (context) => { await context.Response.WriteAsync("Hello World"); }); } } 

プロジェクトを実行すると、ログインとパスワードを入力するウィンドウが表示されるはずです。

正しいログイン-habra、パスワード-habrを入力すると、 Hello Worldが表示されます。 したがって、 middlewareコンポーネントを記述することは難しくありません。

おわりに


この記事では、OWINの基本を紹介しました。 コンポーネントを接続して作成し、リクエストのパイプラインに埋め込み、Microsoftの推奨事項に従ってモジュールを作成するのがいかに簡単でシンプルであるかを確認しました。

著者向け


ご友人、ご自身の資料でコラムをサポートすることに興味がある場合は、すべての詳細を議論するためにvyunev@microsoft.comまでご連絡ください。 ASP.NETおよびその他のトピックについて興味深い話ができる著者を探しています。

著者について


Bobik Vyacheslav Borisovich、
Radarioの.NET開発者

3年の経験を持つ若い.Netプログラマー。 ASP.NET MVCの開発者、WindowsおよびWindows Phone向けアプリケーションの作成者。

Source: https://habr.com/ru/post/J275817/


All Articles