AddMvc()
を使用することは、サービスを制御するための優れたオプションであることに気づかずに、デフォルトのAddMvcCore()
サービスを使用する多くのASP.NET Core Web APIプロジェクトを見てきました。
AddMvcCore()
となぜそれが優れているのですか?を使用して、ASP.NET Core Web APIを正確に実装する方法
AddMvc()
とAddMvcCore()
の違いは何ですか?最初に理解しておくべき重要なことは、AddMvc()
はAddMvcCore()
のプリロードバージョンにすぎないということです。 AddMvc()
拡張の正確な実装は、 GitHubリポジトリ で確認できます。
私は次の人と同じくらいデフォルトのVSテンプレートを使うのが好きですが、時にはそれが間違った選択であるときを知る必要があります。私は、これらのデフォルトのサービスを単に「元に戻す」ことを目的とするのではなく、これらのデフォルトのサービスを「元に戻す」試みに傾いている複数のガイドをオンラインで見ました。
オープンソースであるASP.NET Coreの出現により、「魔法」を失うことを恐れずにレイヤーを剥がして下位レベルで作業することができない理由は、実際にはありません。
注:定義は、この回答のコンテキストのみを対象としています。主にわかりやすくするためと理解を深めるためです。
この答えは、「最小」ではなく「純粋」に傾いています。理由を説明したいので、私が話していることはより明確です。
最小。「最小」ソリューションは、を呼び出しさえしない実装ですAddMvcCore()
method at all。この理由は、MVCは実際には、独自のWeb APIをアセンブルするための「必須」コンポーネントではなく、追加の依存関係によりコードにある程度の重みが確実に追加されるためです。このシナリオでは、AddMvcCore()
メソッドを使用していないため、ここにアプリケーションに挿入することもありません。ここでは
_public void Configure(IApplicationBuilder app)
{
app.UseMvc(); // you don't need this
}
_
これは、独自のルートをマッピングし、独自の方法でcontext
に応答することを意味します。これは実際にはまったく難しいことではありませんが、トピックから外れているため、飛び込みたくはありませんが、最小限の実装の小さな味です:
_public void Configure(IApplicationBuilder app)
{
app.Map("/api", HandleMapApi);
// notice how we don't have app.UseMvc()?
}
private static void HandleMapApi(IApplicationBuilder app)
{
app.Run(async context =>
{
// implement your own response
await context.Response.WriteAsync("Hello WebAPI!");
});
}
_
多くのプロジェクトにとって、「最小限の」アプローチとは、MVCにある機能の一部を放棄することを意味します。設計パターン、利便性、保守性、コードフットプリント、そして最も重要なパフォーマンスとレイテンシのバランスが取れているため、オプションを比較検討し、この設計パスが正しい選択かどうかを確認する必要があります。 簡単に言うと、「最小限の」ソリューションとは、コードとリクエストの間のサービスとミドルウェアを最小限に抑えることを意味します。
Pure。「純粋な」解決策(この回答の文脈に関する限り)は、「事前バンドル」されるすべてのデフォルトのサービスとミドルウェアを避けることです。 "AddMvc()
を最初に実装しないことで。代わりに、次のセクションでさらに説明するAddMvcCore()
を使用します。
AddMvcCore()
を使用して独自のサービス/ミドルウェアを実装する最初に始めることは、ConfigureServices
をAddMvcCore()
を使用するようにセットアップすることです。 GitHubリポジトリ を見ると、AddMvc()
が標準のサービス/ミドルウェアのセットでAddMvcCore()
を呼び出していることがわかります。
「不要」として際立っているサービス/ミドルウェアの一部を次に示します。
_var builder = services.AddMvcCore(); builder.AddViews(); builder.AddRazorViewEngine(); builder.AddRazorPages();
_
これらのデフォルトサービスの多くは、一般的なWebプロジェクトには適していますが、通常は「純粋な」Web APIには望ましくありません。
以下は、Web APIにAddMvcCore()
を使用したConfigureServices
のサンプル実装です。
_public void ConfigureServices(IServiceCollection services)
{
// Build a customized MVC implementation, without using the default AddMvc(),
// instead use AddMvcCore(). The repository link is below:
// https://github.com/aspnet/Mvc/blob/release/2.2/src/Microsoft.AspNetCore.Mvc/MvcServiceCollectionExtensions.cs
services
.AddMvcCore(options =>
{
options.RequireHttpsPermanent = true; // this does not affect api requests
options.RespectBrowserAcceptHeader = true; // false by default
//options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
// these two are here to show you where to include custom formatters
options.OutputFormatters.Add(new CustomOutputFormatter());
options.InputFormatters.Add(new CustomInputFormatter());
})
//.AddApiExplorer()
//.AddAuthorization()
.AddFormatterMappings()
//.AddCacheTagHelper()
//.AddDataAnnotations()
//.AddCors()
.AddJsonFormatters();
}
_
上記の実装は、ほとんどAddMvc()
拡張メソッドの複製ですが、他の人がこれを行うことの追加の利点を確認できるように、いくつかの新しい領域を追加しました。
Accept
ヘッダーが認識されるかどうかを確認できます。「純粋な」ソリューションのこの例があれば、AddMvcCore()
を使用する利点がわかり、快適に使用できます。
ASP.NET CoreのWebホスト上での作業中にパフォーマンスと遅延を制御することに真剣に取り組んでいる場合、「最小限の」ソリューションを深く掘り下げて、要求パイプラインのエッジで対処するのではなく、 MVCミドルウェアによって動きが取れなくなります。
ミドルウェアパイプラインがどのように見えるかを視覚的に見てください...私の定義では、レイヤーが少ないということは「最小限」を意味しますが、「純粋」はMVCのクリーンバージョンにすぎません。
詳細については、Microsoftのドキュメントをご覧ください。 ASP.NET Core Middleware Fundamentals