図4に示すように、第一のHttpContextオブジェクト
私たちのASP.NETコアミニは、7つの中核オブジェクトが構築されて構成されています。最初のものは非常に精通しているHttpContextオブジェクトである、それはASP.NETコアを使用して、最も頻繁にターゲット・アプリケーションの開発と言うことができます。HttpContextの性質を説明するために、パイプラインの面でレベルからの要求に対処する必要があります。ミドルウェアサーバーとパイプ複数のモニタから構成され、最終的な応答サーバは、要求を、トランスポート層を担当して受信するために、それがクライアントによって送信された要求を受信した場合、それ以降の中間に分配される必要があります処理のため。私たちは、ほとんどの場合、自分の要求処理タスクを終了した後も、後続のミドルウェアに要求を必要とミドルウェアについて。サーバミドルウェア、貫通ミドルウェアとの間の分布と要求コンテキスト共有方法の。
上記のようにサーバが要求を受信した場合、それはすべてのミドルウェアは、次に、要求を処理するために、この文脈で正確にどのようなことが運ぶコンテキスト情報のHttpContextオブジェクトである、のHttpContextで表されるコンテキスト・オブジェクトを作成しますか?我々は非常に明確、すなわち、要求を受信し、定義したHTTPトランザクション(トランザクション)は、応答を送信するので、要求と応答は、2つの基本的な要素であり、コアのHttpContextベアラコンテキスト情報であることを知っています。
アプリケーションは、入力された情報を取得するすべての現在のリクエストのHttpContextを活用することができますように、我々は、入力として理解できるように、要求出力応答が、理解されるべきで、また、我々が必要とする仕事出力のすべてを完了するために使用することができます。ASP.NETコアMiniがあるとして、この目的のために、我々は定義のHttpContextのミニマリストのバージョン。
パブリック クラスのHttpContext { 公共 HttpRequestのリクエスト{ 取得します。} 公共 のHttpResponse応答{ 得ます。} } パブリック クラスのHttpRequest { 公共 ウリのURL { 取得します。} 公共 NameValueCollectionのヘッダ{ 得ます。} パブリック ストリームボディ{ 得ます。} } パブリック クラスのHttpResponse { 公共 NameValueCollectionのヘッダ{ 取得します。} パブリック ストリームボディ{ 得ます。} 公共 のintのStatusCode { 得ます。セット;} }
上記コードフラグメントに示されているように、のHttpContext要求と応答は、その特性の2で表され、要求および応答、などのそれらの対応するタイプのHttpRequestとのHttpResponseあります。前者によって、我々は要求、ハンドセットとメインコンテンツ、後者の使用のアドレスを取得することができ、我々は、応答ステータスコードを設定することができ、ヘッダが設けられ、メインコンテンツすることができます。
5、RequestDelegate第二の目的
RequestDelegateは、私たちが紹介する第二のコアオブジェクトです。我々は完全にデリゲートオブジェクトの性質を理解するために、パイプラインの観点からだけ持って、これは前述したデリゲート(委任)オブジェクトとのHttpContextある名前から見ることができます。
良いデザインは「シンプル」なデザインでなければならないこと:ソフトウェアアーキテクチャの設計は、このような理解を持っています。私は開発フレームワークを設計していたときにそう、私は常に自分自身を語ってきた:「で簡単にすることができませんでした?。」:私たちは、「シンプル」な資質の上で説明したデザインASP.NETコア・パイプラインパイプライン=サーバー+ミドルウェア。しかし「で簡単なことではありません?」それが実際に可能であった:私たちは「のHttpHandler」シングルに複数のミドルウェアを構築することができ、その後、全体ASP.NETコアフレームワークは、より単純な表現を持っています:パイプライン=サーバー+のHttpHandler。
我々のHttpHandlerのであればそれを表現するには?私たちは考えることができます:現在の要求のすべての入力と出力はのHttpContextで表現されているので、アクションのHttpHandler <のHttpContext>オブジェクトとして表現することができます。だから、のHttpHandlerアクションによって<のHttpContext>それにASP.NETコアで表現?そうでもない、その理由は非常に単純です:アクション<のHttpContext>操作の処理「同期」の唯一の明示要求することができます(ボイド)、しかし、HTTPの要求は、同期または非同期のいずれかであることができ、実際にはより多くの非同期です。
だから、.NETのコアの世界でどのように同期または非同期操作、それを表現するには?あなたはことを考えるべきタスクのオブジェクト、のHttpHandlerが自然のように表現することができるのFunc <HttpContextを、タスク>オブジェクト。このデリゲートオブジェクトのはあまりにも重要であるため、私たちは、としてそれを定義するセパレートタイプ。
パブリックデリゲートタスクRequestDelegate(のHttpContextコンテキスト)。
実際には、とのFunc <HttpContextを、タスク>と同じです
6、ミドルウェア第三の目的
在对RequestDelegate这个委托对象具有充分认识之后,我们来聊聊中间件又如何表达,这也是我们介绍的第三个核心对象。中间件在ASP.NET Core被表示成一个Func<RequestDelegate, RequestDelegate>对象,也就是说它的输入和输出都是一个RequestDelegate。
对于为什么会采用一个Func<RequestDelegate, RequestDelegate>对象来表示中间件,很多初学者会很难理解。我们可以这样的考虑:对于管道的中的某一个中间件来说,由后续中间件组成的管道体现为一个RequestDelegate对象,由于当前中间件在完成了自身的请求处理任务之后,往往需要将请求分发给后续中间件进行处理,所以它需要将由后续中间件构成的RequestDelegate作为输入。
当代表中间件的委托对象执行之后,我们希望的是将当前中间件“纳入”这个管道,那么新的管道体现的RequestDelegate自然成为了输出结果。所以中间件自然就表示成输入和输出均为RequestDelegate的Func<RequestDelegate, RequestDelegate>对象。
IapplicationBuilder接口中定义Use方法
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
7、ApplicationBuilder 第四个对象
ApplicationBuilder是我们认识的第四个核心对象。从命名来看,这是我们接触到的第二个Builder,既然它被命名为ApplicationBuilder,意味着由它构建的就是一个Application。那么在ASP.NET Core框架的语义下应用(Application)又具有怎样的表达呢?
对于这个问题,我们可以这样来理解:既然Pipeline = Server + HttpHandler,那么用来处理请求的HttpHandler不就承载了当前应用的所有职责吗?那么HttpHandler就等于Application,由于HttpHandler通过RequestDelegate表示,那么由ApplicationBuilder构建的Application就是一个RequestDelegate对象。
由于表示HttpHandler的RequestDelegate是由注册的中间件来构建的,所以ApplicationBuilder还具有注册中间件的功能。基于ApplicationBuilder具有的这两个基本职责,我们可以将对应的接口定义成如下的形式。Use方法用来注册提供的中间件,Build方法则将注册的中间件构建成一个RequestDelegate对象。
public interface IApplicationBuilder { IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); RequestDelegate Build(); }
如下所示的是针对该接口的具体实现。我们利用一个列表来保存注册的中间件,所以Use方法只需要将提供的中间件添加到这个列表中即可。当Build方法被调用之后,我们只需按照与注册相反的顺序依次执行表示中间件的Func<RequestDelegate, RequestDelegate>对象就能最终构建出代表HttpHandler的RequestDelegate对象。
public class ApplicationBuilder : IApplicationBuilder { private readonly List<Func<RequestDelegate, RequestDelegate>> _middlewares = new List<Func<RequestDelegate, RequestDelegate>>(); public RequestDelegate Build() { _middlewares.Reverse(); return httpContext => { RequestDelegate next = _ => { _.Response.StatusCode = 404; return Task.CompletedTask; }; foreach (var middleware in _middlewares) { next = middleware(next); } return next(httpContext); }; } public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware) { _middlewares.Add(middleware); return this; } }
在调用第一个中间件(最后注册)的时候,我们创建了一个RequestDelegate作为输入,后者会将响应状态码设置为404。所以如果ASP.NET Core应用在没有注册任何中间的情况下总是会返回一个404的响应。如果所有的中间件在完成了自身的请求处理任务之后都选择将请求向后分发,同样会返回一个404响应。
Core中的IapplicationBuilder定义
// 摘要:Defines a class that provides the mechanisms to configure an application's requestpipeline. public interface IApplicationBuilder { // Gets or sets the System.IServiceProvider that provides access to the application'sservice container. IServiceProvider ApplicationServices { get; set; } // // 摘要: // Gets the set of HTTP features the application's server provides. IFeatureCollection ServerFeatures { get; } // // 摘要: // Gets a key/value collection that can be used to share data between middleware. IDictionary<string, object> Properties { get; } // // 摘要: // Builds the delegate used by this application to process HTTP requests. // 返回结果: // The request handling delegate. RequestDelegate Build(); // // 摘要: // Creates a new Microsoft.AspNetCore.Builder.IApplicationBuilder that shares the //Microsoft.AspNetCore.Builder.IApplicationBuilder.Properties of this Microsoft.AspNetCore.Builder.IApplicationBuilder. // // 返回结果: // The new Microsoft.AspNetCore.Builder.IApplicationBuilder. IApplicationBuilder New(); // // 摘要: // Adds a middleware delegate to the application's request pipeline. IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware); }