Microsoft Webフレームワークの進化。 ASP.NET vNext





変更の前提条件



ネットワークでのASP.NET vNextのリリースに関するニュースは、更新で提案された最も興味深いイノベーションの発表とともに、非常に急速に広まりました。 ASP.NET MVC 6は新しい名前を受け取り、Microsoft Webフレームワークフレームワーク(MS)で本当に新しいものとして位置付けられています。 発表されたvNextの変更の重要性を最も完全に理解するために、.NETプラットフォームでのWebアプリケーションの現在の実装の機能を思い出します。



典型的なASP.NET MVCアプリケーションは、HttpApplicationクラス(System.Web)を拡張するGlobal.asaxファイルで構成されているため、MVCの個々のコンポーネントを構成することで、Http要求を処理するための望ましい動作を追加します。 クラシックASP.NET MVCでは、ルータークラス(System.Web.Routing)は、コントローラーファクトリを作成し、さらにリクエスト処理パイプを開始する標準動作(MvcRouteHandler)で、目的のHttpHandlerにリダイレクトすることにより、Httpリクエストの処理に不可欠な部分です。 これらのコンポーネントは、MS-インターネットインフォメーションサービス(IIS)のWebサーバーと密接に結びついています。IISは、HttpHandlersおよびHttpContext(http要求/応答パラメーターへのアクセス)を使用して要求を処理します。 MVCのASP.NET Webフォームでこれらのコンポーネントを広く使用することは、IISとの密接な統合を暗示し、アプリケーションをホストするために代替Webサーバーを使用することを不可能にしました。 時間の経過とともに、これらの状況は開発者コミュニティからより多くの批判を引き起こし、ASP.NET MVCの開発において実際にはあまり有利な要因ではありませんでした。







Web Apiプロジェクトの開発の一環として、状況を修正する試みが行われました。 MS WCFフレームワークからの移行中、開発者は、より便利なMVCを優先して「契約バインディング」の概念に基づいてRESTfulサービスを構築するアプローチを放棄しました。 実際、新しいフレームワークの開発者は、上記のASP.NET MVCの欠陥に目を向けることができました。 Web Apiは、HttpContext.Request、HttpContext.Responseのアダプターのおかげで、これらの同じSystem.Webコンポーネントを直接使用しませんでした-HttpControllerHandler(Web Apiアプリケーションへのエントリポイント)が指定されたオブジェクトを変換した、更新されたHttpRequestMessage、HttpResponseMessage構造の抽象化 また、更新されたスタック(フィルター、ディスパッチャー、委任ハンドラー、コントローラー)の実装に基づいて、ネストされたHttpMessageHandlers(System.Net.Http)のチェーンを介して要求を処理することにより、IIS HttpHandlersへの依存がなくなりました。







これらすべての変更により、Web Apiアプリケーションはホストから独立し、OWIN(Open Web Interface)仕様のフレームワーク内で開発されました。 キーはミドルウェアの概念でした-Webアプリケーションコンポーネント(IISの場合-HttpModules)およびアプリケーションデリゲート。HttpContextの代わりに、IDictionary <string、object>の形式のハッシュマップで要求/応答パラメーターのはるかに抽象的なセットと対話します。







すべての利点、柔軟性、拡張性の向上、およびアーキテクチャ上の弱点に対する多くの修正にもかかわらず、Web Apiは、シングルページアプリケーション(SPA)に焦点を合わせたMVCの完全な代替品になることはできませんでした。 同時に、1つのフレームワークが他のフレームワークと干渉しませんでした。 さらに、IISがホスティングに使用され、認証などに一般的なHttpモジュールを使用できる場合でも、同じWebアプリケーションでうまく連携しました。 それにもかかわらず、検討されたアプローチでは、アプリケーションの責任を明確に分離し、Web ApiとMvcが完全に異なるパイプラインを使用してリクエストを処理する機能を考慮する必要がありました。 後者は、開発者に異なる種類の複雑さを追加し、vNextと呼ばれる新しいバージョンのフレームワークでの後続のリファクタリングを提案しました。



ASP.NET vNextプロジェクトテンプレート



新しいWebアプリケーションで最初に注目するのは、web.config、packages.config、AssemblyInfo.cs構成ファイルさえないことです。







ソリューション構造には2つのファイルしかありません。



ここで、VSプロジェクトのプロパティを調べたので、ASP.NETプロジェクトに装備されていた豊富なオプションは表示されません。 合計で、2つのタブを使用できます。一般-構築中の名前空間とアプリケーションタイプの構成。 [デバッグ]タブで、アプリケーションを使用できるポート番号。

さらに興味深いのは、プロジェクトの実際のproject.json構成ファイルです。 おおよそ次のようになります。







プライマリセットは、2つのキーのみを提供します。



プロジェクトの構造におけるこのような劇的な変更は、新しいRoslynコンパイラの使用によるものです。これにより、ランタイムはILでソースコードをコンパイルして実行できます。 Roslynの機能は、新しいK言語ランタイム(KLR)を支えました。 現時点では、.NETデスクトップモードまたはコアCLRでプロジェクトを起動するための2つのオプションがあります(アルファ版では、モードはWin 8からKLRでのみ使用可能です)。 Kバージョンマネージャー(KVM)/ Kパッケージマネージャー(KPM)を使用してプロジェクトをビルドすることもできます-Kに付属のコンソールユーティリティを使用すると、インストールされたバージョンのKRE(Kランタイムエンジン)を個別に管理し、project.jsonに基づいてアプリケーションをアンパックして実行できます。 詳細については、 github.com / aspnet / homeをご覧ください



ASP.NET vNext Webアプリケーションの構造



プロジェクト内の唯一のソースコードファイルはStartup.csで、Microsoft.AspNet.Builder名前空間へのリンクと、OWINベースのアプリケーションに類似したクラス構造が含まれています。 1つのメソッドがあります-タイプIBuilderの入力パラメーターで構成します。 プロジェクトはコンパイルおよび開始されますが、答えとして何も返しません(IISは要求ハンドラーを見つけられず、ファイルシステムにアクセスしようとするため、「403rd」を返します)。これはミドルウェアを追加しなかったためです。







www.asp.net/vnextでは、静的拡張メソッド(UseWelcomePage)を呼び出して最も単純な要求ハンドラーを追加するように招待されていますが、IBuilderインターフェイスの詳細全体が隠されているため、あまり興味がありません。 その定義をさらに深く掘り下げてみましょう。



using System; namespace Microsoft.AspNet.Builder { public interface IBuilder { IServiceProvider ApplicationServices { get; set; } IServerInformation Server { get; set; } RequestDelegate Build(); IBuilder New(); IBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); } }
      
      







コードをナビゲートするには、OWINのミドルウェアの概念が、Httpリクエストパラメーターのリストを受け取り、それに対して何らかの変換を実行してTaskを返すApplication Delegateを直接参照することを覚えておく必要があります。



 Func<IDictionary<string, object>, Task>
      
      







OWINには、IAppBuilderインターフェイスレベルで静的なExtensionsメソッドもありました。これにより、より便利な構造化バージョンのコンテキストであるIOwinContextを使用してミドルウェアを追加できました。 HttpContextを直接操作する必要があるため、vNextで少し変更されました。 後者は現在、Microsoft.AspNet.Http名前空間にあり、ASP.NET MVCのHttpContextBaseラッパーの場合のように、System.WebのHttpContextとは関係ありません。



 public delegate Task RequestDelegate(HttpContext context);
      
      







したがって、すべてが徐々に適切に配置されます-vNextのRequestDelegateは、まさにOWIN Application Delegateです。

Useメソッドの元の実装に新しいミドルウェアを追加するには、RequestDelegate型のネストされたデリゲートを含む汎用デリゲートをパラメーターとして渡します。 外部の汎用デリゲートは、httpリクエストを処理するための追加のパイプライン全体を指します。RequestDelegate-Http Handlerの処理を行います。

モジュールを追加した例を見てみましょう。これにより、状況が少し明確になるはずです。



 public void Configure(IBuilder app) { app.Use(next => httpContext => httpContext.Response.WriteAsync("Executed before all followers." + Environment.NewLine) .ContinueWith(task => next(httpContext))); app.Use(next => httpContext => next(httpContext) .ContinueWith(task => httpContext.Response.WriteAsync("Executed after all followers." + Environment.NewLine))); app.Use((httpContext, next) => httpContext.Response.WriteAsync("Hello world middleware." + Environment.NewLine)); }
      
      







ご覧のとおり、ミドルウェアを構成する場合、ハンドラーの委任Web Apiと非常によく似た動作があります。このパイプラインでは、後続のパイプライン全体の現在のモジュールから実行シーケンスを柔軟に制御できます(次のパラメーター)。 Useに渡されたラムダ式内にHttp要求処理を追加するだけです。







OWIN自体については、vNextはこのインターフェイスと完全に互換性があります。 Microsoft.AspNet.Builder名前空間には、Owin Application DelegateからvNext RequestDelegateに移行するためのアダプターを作成するIBuilderの静的拡張メソッドのクラスが含まれています。



 using AddMiddleware = Action<Func<Func<IDictionary<string, object>, Task>, Func<IDictionary<string, object>, Task>>>; public static AddMiddleware UseOwin(this IBuilder builder) { .... }
      
      







このアプリケーションでは、AddMiddlewareを使用して、プラットフォームの内部実装に依存して、OWIN環境ディクショナリとvNext HttpContextを相互作用させることができます。 この拡張により、フレームワークの新しいバージョンでOWINコンポーネントを使用するのが簡単になります。



重要な機能のうち、OWIN AppBuilderとは異なり、vNext IBuilderインターフェイスには、Webサーバーによってアプリケーションによって初期化された組み込みのApplicationServicesサービスロケーターも含まれていることに注意してください。 このプロパティは、Webホストアプリケーションレベルサービスアクセスを提供します。



vNext HttpContext



アプリケーションの構造により、更新されたvNext HttpContextが少しわかりました。 予想どおり、コンテキストクラス自体、RequestおよびResponseは抽象として宣言されています。 ベビーベッドから提供されるMicrosoft.AspNet.Hostingホストの実装のHttpContextは、ミドルウェアチェーンへの各呼び出しの前にDefaultHttpContextオブジェクトによってインスタンス化されます。 コンテキストにはAbortメソッドがあり、IDisposableインターフェイスを実装し、2つのアプリケーションロケーターサービスApplicationServicesおよびRequestServicesに対応するコンテナーライフサイクルを提供します。これは、ASP.NET MVCの以前のバージョンと比較して、アプリケーションレベルでの構造マップのより便利な形成を支持することを明確に表しています。



VNextは、HttpFeaturesを使用して新しいコンテキスト拡張メカニズムを追加します。 コンテキストインターフェイスレベルでは、拡張機能を取得および追加するための2組のメソッドを提供します(オブジェクトと汎用ラッパーのパッキングを介して)。



  public abstract object GetFeature(Type type); public abstract void SetFeature(Type type, object instance); public virtual T GetFeature<T>() { return (T)GetFeature(typeof(T)); } public virtual void SetFeature<T>(T instance) { SetFeature(typeof(T), instance); }
      
      







ASP.NETの更新バージョンでは、このアプローチを使用して、ホストアプリケーション/サーバー固有の機能が初期化され、リクエストパラメーター、認証、キャッシング、および個々のミドルウェアコンポーネントによるWebソケットの操作まで、HttpContextの最初の呼び出しから始まるコンテキストを動的に形成します。 基本的な実装では、RequestはMicrosoft.AspNet.Builderで定義されたインターフェイスをほぼ完全に使用して、HttpFeaturesからコンポーネントを取得します。 このようにコンテキストを形成することにより、HttpContexの基本構造に限定されない、ホストレベルでの特定のWebサーバー固有の機能の実装を個別のコンポーネントの特定のインターフェイスの背後に隠すことができます。



vNext MVC



Webアプリケーション自体の構築という観点から最も期待される革新は、1つのフレームワークのフレームワーク内でのASP.NET MVCとWeb Api機能の組み合わせです。これにより、共通のパイプラインを使用してHttp要求を処理できます。



MVCの動作をvNextに追加するには、2つのミドルウェアモジュールを接続して構成する必要があります。





  public void Configure(IBuilder app) { app.UseServices(services => services.AddMvc()); app.UseMvc(router => router.MapRoute("DefaultHome", "{controller}/{action}/{id?}", defaults: new { Controller = "Home", Action = "Index" })); }
      
      







これらの最初のものは、標準のMVCコンポーネントの実装を提供するサービスのセットであり、パイプライン全体で使用され、個々の抽象化のレベルで要求を処理します。 アクションコンテキストのプロバイダー、コントローラーファクトリー、モデルバインディング、ビューエンジンの提供などについて話します。 DIマッピングを使用したサービスの説明は、Microsoft.AspNet.Mvc.MvcServices.csクラスで確認できます。



2つ目はRouterHandlerで、これはvNextで非同期RouteAsyncメソッドを持つIRouterインターフェイスによって表されます。



  public interface IRouter { Task RouteAsync(RouteContext context); string GetVirtualPath(VirtualPathContext context); }
      
      







デフォルトでは、インターフェースはMvcRouteHandlerクラスを実装します。 フレームワーク固有の機能に基づく以前のバージョンのルーティング(MVC-HttpHandler、Web Api-DelegatingHandler)とは異なり、今回は、MVCコンポーネントのセットを使用してサービスロケーターから受信した個々のインターフェイスメソッドの呼び出しのみを提供します。 このクラスがActionContextを受け取り、ControllerFactoryと組み合わせてIActionInvokerサービスを使用して要求を処理するための追加のパイプラインを開始します。 このアプローチを使用する主な利点は明らかであり、以前は存在しなかったフレームワークのマージに必要な汎用性を提供します。



MVCの新しいバージョンにおけるもう1つの積極的な変更点は、サービスメソッドの完全な非同期実行モードです。 同様の方法で、Web Apiにパイプが実装され、Webサーバーストリームの作業プールからリソースを待機することに関連する操作を完全に削除できるようになりました。 これまで、MVCは「すぐに使える」非同期コントローラーのみを提供していました。



MVCのコントローラーは、vNextでHttp要求を処理するための主要な作業単位として採用されました。 IActionResultインターフェイスは、アクションの結果の後処理とシリアル化に使用されます。 この点での機能的MVCは、概念的には同じままでした。 Web Apiでうまく機能した主な拡張機能については、現在パイプラインvNextに追加されていません。 たとえば、コンテンツネゴシエーションサービスを使用してフォーマッタを決定するメカニズム。 IActionResultを実装しないクラスのインスタンスがコントローラーアクションから返される場合、JSONフォーマッターが使用されます。



更新されたプロジェクトテンプレートへの移行により、アプリケーション構成メカニズムが大幅に変更されました。 現在では、古いweb.configの代わりに、キーと値のペアの階層構造を表すconfig.jsonが使用されます。







コードレベルで直接、Microsoft.Framework.ConfigurationModel名前空間から一連のユーティリティが提供され、さまざまな構成ソースからのキーをマージします。たとえば、Kコンソールに渡されるホストアプリケーションの起動パラメーター。 Webアプリケーションのproject.json、config.jsonファイルで定義されたペア。



記載されていないコンポーネントと同様に、各コンポーネントについて、個別のレビューを書くことができ、それが単独ではないことを確認できます。 新しいフレームワークの機能コンポーネントのリストがまだ確定していないことを考えると、その主要コンポーネントの動作の基本的な理解に限定されます。



まとめ



ASP.NET MVC vNextのアルファ版に精通した後、開発者の変化は非常に劇的なものになると予想しています。 これらは、ASP.NETの徹底的なリファクタリングだけでなく、更新されたランタイムへのフレームワークの適応にも関連付けられています。



アプリケーションレベルでは、内部概念の変更は非常に限られており、OWINおよびASP.NET MVCの以前のバージョンを扱った開発者にとって直感的です。



フレームワーク自体の観点から最も重要なのは、オープンなWebインターフェースへの移行と、ホストとWebアプリケーション間の責任の明確な描写です。 抽象化の構成を高品質に更新し、柔軟な拡張オプションを追加することにより、Webアプリケーション開発の新しい可能性が開かれます。



有用なリソース:


www.asp.net/vnext

github.com/aspnet

blogs.msdn.com/b/webdev/archive/2014/06/03/asp-net-vnext-in-visual-studio-14-ctp.aspx

www.asp.net/aspnet/overview/owin-and-katana

blogs.msdn.com/b/dotnet/archive/2014/05/12/the-next-generation-of-net-asp-net-vnext.aspx



All Articles