.NET 6 Preview 4 における ASP.NET Core のアップデート

みなさんごきげんよう。本記事は、2021 年 5 月 25 日（米国時間）ポストされた "**ASP.NET Core updates in .NET 6 Preview 4**" の速報的なアレというか意訳のようななにかとなります。内容については下記が原文で、正となります。

https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-4/

なお、結構長いです。おやつなどを食べながら優雅に御覧いただくとよいと思います。本当に長い。

#はじめに
[.NET 6 Preview 4](https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-4/) がリリースされました。今回はその中でも ASP.NET Core に追加された、たくさんの素晴らしい新機能について紹介したいと思います。

今回のプレビューリリースでの新機能をご紹介します。

* "最小限の API" の導入
* 非同期ストリーミング
* HTTP ロギング ミドルウェア
* 新規プロジェクトの既定の起動プロファイルに Kestrel を使用
* `IConnectionSocketFeature`
* シングルページ アプリケーション (SPA) テンプレートの改良
* .NET Hot Reload の更新
* Razor コンポーネントにおけるジェネリック型制約
* Blazor のエラー境界
* Blazor WebAssembly ahead-of-time (AOT) コンパイル
* .NET MAUI Blazor アプリ
* その他のパフォーマンスの向上

https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-4/
#早速使ってみる
まず、.NET 6 Preview 4 で ASP.NET Core を使い始めるには、[.NET 6 SDK](https://dotnet.microsoft.com/download/dotnet/6.0) をインストールしましょう。

https://dotnet.microsoft.com/download/dotnet/6.0

Windows 版 Visual Studio を使用している場合は、[Visual Studio 2019 16.11 の最新版](http://visualstudio.com/preview) (※) を、また Mac OS 版をお使いの場合は、[Visual Studio 2019 for Mac 8.10 の最新版](https://docs.microsoft.com/visualstudio/releasenotes/vs2019-mac-preview-relnotes)  (※) をインストールいただくことをおすすめします。
(※訳注 2021/05/26 JST 現在、ここで言う「最新版」は Windows 版、Mac 版ともに**プレビュー版**の利用を指しています) 

* Windows 版

http://visualstudio.com/preview

* Mac OS 版

https://docs.microsoft.com/visualstudio/releasenotes/vs2019-mac-preview-relnotes

#既存プロジェクトをアップグレードしてみる
既存の ASP.NET Core アプリを .NET 6 Preview 3 から .NET 6 Preview 4 にアップグレードするには、以下の手順を実行します。

* すべての Microsoft.AspNetCore.* パッケージの参照を <font color="Red">6.0.0-preview.4.* </font> に更新します。
* すべての Microsoft.Extensions.* パッケージの参照を <font color="Red">6.0.0-preview.4.* </font>に更新します。

ASP.NET Core for .NET 6 の変更点は、以下のリストをご覧いただくとよいでしょう (リンク先英語)。

https://docs.microsoft.com/dotnet/core/compatibility/6.0#aspnet-core

#最小限の API の導入
Web アプリケーションにおけるホスティングとルーティングを実現するためにはどのようにすればよいでしょうか。

`.NET 6` では、なんと、**ただ新しく、ASP.NET Core の空の Web アプリを作成いただくだけで完全に機能する HTTP API ができてしまいます**。たった 1 つのファイルと数行のコードだけのいわば「**最小限の API**」で、`ASP.NET MVC` の利点を享受できる、完全に機能する HTTP API ができてしまうのです。これは便利ではないでしょうか。

```
dotnet new web -o MinApi
```

この「最小限の API」、.NET を使って初めて Web アプリを作るんだけど…という初心者の方にとってうれしいだけでなく、小規模なマイクロ サービスや HTTP API を構築したいという方まで幅広い方々におすすめです。
![VSC](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/new-min-api.gif)
↑手順はたったこれだけ
#新しいルーティング API
新しいルーティング API により、**ユーザーはあらゆるタイプのメソッドにルーティングすることができます**。これらのメソッドでは、コントローラ ライクなパラメータ バインディング、JSON フォーマット、アクション結果の実行などを利用できます。

* **Before**（既存の [Map](https://docs.microsoft.com/aspnet/core/fundamentals/routing#routing-basics) API を使用した場合）

```diff_c_sharp
app.MapGet("/", async httpContext =>.
{
    await httpContext.Response.WriteAsync("Hello World!");
});
```
https://docs.microsoft.com/aspnet/core/fundamentals/routing#routing-basics

* **After**（新しい `Map` のオーバーロードを使用）

```diff_c_sharp
app.MapGet("/", (Func<string>)(() => "Hello World!"));
```

#C# 10 の改良
これらの API は、トップレベル ステートメントなど、C# の新しい機能をすでに利用しています。今年 (訳注 2021 年) の後半に .NET 6 と併せてリリースされる予定の C# 10 では、さらに使い勝手が良くなります。

例えば、明示的なキャスト `(Func<string>)` はもういらなくなります。たとえば、[C# 10](https://github.com/dotnet/csharplang/blob/main/proposals/lambda-improvements.md) の機能がフル実装された暁には、こんな感じになります。やったね。

![VSC2](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/min-apis-cs10.gif)

https://github.com/dotnet/csharplang/blob/main/proposals/lambda-improvements.md

MVC コントローラのアクションで利用可能な属性やその他の機能を諦めずとも、クラスやメソッドの使用からラムダの使用へと移行することができるようになります。

#新しいホスティング API 
新しい空の Web テンプレートは、`.NET 6 Preview 4` で導入された新しいホスティング モデルを使用しています。

```diff_c_sharp
var app = WebApplication.Create(args);
app.MapGet("/", (Func<string>)(() => "Hello World!"));
app.Run();
```
新しいルーティング API の使用方法はこれだけに限りません。
以下は、サービスを構成してミドルウェアを追加し、新しいホスティング モデルを使用するようにアップデートされた既存の Web アプリケーション例です。

```diff_c_sharp
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "Api", Version = "v1" });
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Api v1"));
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();
```

このように、新しいホスティング API をつかえば、あらゆる ASP.NET アプリを構成し、起動するために必要な定型文の量を減らすことができるのです。

#パフォーマンス
確かに便利だとしても、パフォーマンスがいまいちならばつかいものになりませんが、この新しいルーティング API は、コントローラベースの API に比べてはるかにオーバーヘッドが少なくて済みます。
[TechEmpower](https://www.techempower.com/benchmarks/) JSON ベンチマークを例にとり、みてみましょう。新しいルーティング API を使用することで、ASP.NET Core は MVC の 50 万 RPS に対して、80 万 RPS を達成することができました。

![JSONBench](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/min-api-perf.png)

#非同期ストリーミング
ASP.NET Core では、コントローラのアクションからレスポンスの JSON フォーマッタに至るまで、非同期ストリーミングがサポートされるようになりました。アクションから　`IAsyncEnumerable` を返しても、レスポンスの内容が送信される前にメモリにバッファリングされなくなりました。これは、非同期的に列挙できる大規模なデータセットを返す際のメモリ使用量を減らすことができるということを意味しています。

なお、Entity Framework Core (以下、EF Core) では、データベースへの問い合わせ用に `IAsyncEnumerable` の実装を提供しています。.NET 6 で ASP.NET Core の `IAsyncEnumerable` のサポートが改善されたことで、EF Core を ASP.NET Core で使用することがより効率的になります。例えば、以下のコードでは、レスポンスを送信する前に商品データをメモリにバッファリングすることをなくすことができます。

```diff_c_sharp
public IActionResult GetProducts()
{
    return Ok(dbContext.Products);
}
```

しかし、遅延ローディングを使用するように EF Core を設定していると、この新しい動作では、データの列挙中にクエリが同時に実行されることでエラーが発生する可能性があります。以前の動作に戻したい場合は、自分でデータをバッファリングするようにしましょう。

```diff_c_sharp
public async Task<IActionResult> Products()
{
    return Ok(await dbContext.Products.ToListAsync());
}
```

この動作変更の詳細については、以下をご覧ください。

https://github.com/aspnet/Announcements/issues/463

#HTTP ロギング ミドルウェア
HTTP ロギングは、HTTP リクエストと HTTP レスポンスの情報を、ヘッダーとボディ全体を含めて記録する、新しい組み込みミドルウェアです。

```diff_c_sharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpLogging();
}
```
HTTP ロギングは、以下のログを提供します。

* HTTP Request information
* Common properties
* Headers
* Body
* HTTP Response information

HTTPロギングミドルウェアを設定するには、`ConfigureServices()` の呼び出しで `HttpLoggingOptions` を指定します。

```diff_c_sharp
public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpLogging(logging =>
    {
        // Customize HTTP logging here.
        logging.LoggingFields = HttpLoggingFields.All;
        logging.RequestHeaders.Add("My-Request-Header");
        logging.ResponseHeaders.Add("My-Response-Header");
        logging.MediaTypeOptions.AddText("application/javascript");
        logging.RequestBodyLogLimit = 4096;
        logging.ResponseBodyLogLimit = 4096;
    });
}
```

これで、HTTP リクエスト情報を含む新しいログが `Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware` カテゴリに作成されます。

```diff_c_sharp
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Protocol: HTTP/1.1
      Method: GET
      Scheme: https
      PathBase:
      Path: /
      QueryString:
      Connection: keep-alive
      Accept: */*
      Accept-Encoding: gzip, deflate, br
      Host: localhost:5001
      User-Agent: PostmanRuntime/7.26.5
      My-Request-Header: blogpost-sample
      Postman-Token: [Redacted]
```

HTTP ロギングの使用方法については、[以下のドキュメント](https://docs.microsoft.com/aspnet/core/fundamentals/http-logging)をご覧ください。

https://docs.microsoft.com/aspnet/core/fundamentals/http-logging

#新規プロジェクトの既定の起動プロファイルに Kestrel を使用する
![vsc3](https://user-images.githubusercontent.com/4734691/119421431-8450fc80-bcb3-11eb-8f83-7d3140ccf9fe.png)

.NET 6 Preview 4 で作成されたすべての新規プロジェクトについて、既定の起動プロファイルを IIS Express から Kestrel に変更しました。Kestrel の起動はかなり高速化され、アプリ開発時のレスポンスがいい感じに向上しました（どのくらいイイ感じだったかは以下の通り）

|  |IIS Express (単位 ms)  |Kestrel (単位 ms) |% change |
|---|---|---|---|
|Debugging  |4359  |2772  |36%  |
|No debugging |1999  |727  |64%  |

IIS Express は、Windows 認証やポート共有などのシナリオに対応した起動プロファイルとして利用いただけます。

#`IConnectionSocketFeature`
`IConnectionSocketFeature` リクエスト機能は、現在の要求に内在的に関連づけられている受け入れソケットへのアクセスを提供します。これは、`HttpContext` の `FeatureCollection` からアクセスできます。

以下のアプリケーションの例では、受け入れソケットに  `LingerState` プロパティを設定しています。

```diff_c_sharp
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions => listenOptions.Use((connection, next) =>
    {
        var socketFeature = connection.Features.Get<IConnectionSocketFeature>();
        socketFeature.Socket.LingerState = new LingerOption(true, seconds: 10);
        return next();
    }));
});
var app = builder.Build();
app.MapGet("/", (Func<string>)(() => "Hello world"));
await app.RunAsync();
```

#シングルページ アプリケーション（SPA）テンプレートの改良
Angular と React 用の ASP.NET Core プロジェクトのテンプレートを SPA 用の改良されたパターンを使用するようにアップデートしました。これにより、最新のフロントエンド Web 開発の一般的なパターンにおいて、よりフレキシブルに対応できるようになります。

従来、Angular および React 用の ASP.NET Core テンプレートでは、開発時に専用のミドルウェアを使用し、フロントエンド　フレームワーク用の開発サーバーを起動し、ASP.NET Core　から開発サーバーへのリクエストをプロキシするというプロセスでした。フロントエンドの開発サーバーを起動するロジックは、対応するフロントエンド フレームワークのコマンドライン インターフェイスに固有のものであったことから、このパターンで追加のフロントエンド フレームワークをサポートするには、ASP.NET Core に新たなロジックを追加する必要があったのです。

.NET 6 で更新された Angular と React 用の ASP.NET Core テンプレートでは、この配置を反転させ、ほとんどの最新のフロントエンド フレームワークの開発サーバーに組み込まれたプロキシ サポートを利用するようになっています。
これにより、ASP.NET Core アプリを起動すると、フロントエンドの開発サーバーは以前と同様に起動されますが、開発サーバーはその要求をバックエンドの ASP.NET Core プロセスにプロキシするように構成されています。

プロキシを設定するためのフロントエンド固有の構成は、ASP.NET Core ではなくアプリケーションの一部です。ASP.NET Core プロジェクトを他のフロントエンド フレームワークと連携させることも簡単です。Angular と React のテンプレートで確立されたパターンを使用して、選択したフレームワークのフロントエンド開発サーバーを ASP.NET Core のバックエンドにプロキシするように設定するだけで済みます。

ASP.NET Core アプリの起動コードには、シングルページのアプリケーション固有のロジックは必要ありません。開発中にフロントエンド開発サーバーを起動するためのロジックは、新しい [Microsoft.AspNetCore.SpaProxy](https://nuget.org/packages/microsoft.aspnetcore.spaproxy) パッケージによってランタイムにアプリにインサートされます。フォールバック　ルーティングは、SPA 固有のミドルウェアに代わって、エンドポイント　ルーティングを使用して処理されます。

https://nuget.org/packages/microsoft.aspnetcore.spaproxy

このパターンのテンプレートは、Visual Studio で単一プロジェクトとして実行したり、コマンドラインから `dotnet run` を使用して実行することもできます。アプリケーションが公開されると、*ClientApp* フォルダ内のフロントエンド コードがビルドされ、以前と同様にホスト ASP.NET Core アプリケーションの Web ルートに収集され、静的ファイルとして機能するようになります。テンプレートに含まれるスクリプトは、ASP.NET Core の開発証明書を使用し HTTPS を使用するようにフロントエンド開発サーバーを構成してくれます。

#.NET Hot Reload のアップデート
Visual Studio の最新のプレビュー版には、.NET Hot Reload のイニシャル サポートが含まれます。アプリをデバッグする際に、新しい「コード変更の適用」ボタンとデバッグ オプションがさりげなく、それでいて確かな存在感を放っているのに是非お気づきいただきたいところです。（↓コレ）

![codeupdate](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/apply-code-changes-button.png)

「コード変更の適用」ボタンを押すと、ファイルを保存しなくても、エディタで行ったコード変更が実行中のアプリに反映されます。以下の例では、`Counter` コンポーネントを更新し、インクリメントを 1 ではなく 2 にしています。変更が適用されても、現在のカウント情報は失われていないことをお分かりいただけると思います。

![vsc4](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/vs-hot-reload-blazor.gif)

早くお試ししたいという方もいらっしゃると思いますが、2021 年 5 月 26 日 JST 現在、Visual Studio の .NET Hot Reload サポートはまだ絶賛進行中であるため、しばらくは ASP.NET Core アプリで .NET Hot Reload を利用する際にはいくつかの制限があることにご注意ください。

**現時点の制限事項** (2021/5/26 現在)

* 変更を適用するには、デバッガーを接続して実行する必要があります。
* コードの変更は、**C# ファイルにのみ**適用できます。Razor ファイル（.razor、.cshtml）への変更は、今後のアップデートをお待ちください。
* 適用された変更は UI を強制的に更新しません。そのため、UI の更新は手動でトリガーしていただく必要があります。
* 変更は Blazor WebAssembly アプリにはまだ適用できません。

なお、**上記制限事項はあくまで現時点の状況であり、将来の Visual Studio アップデートで対応されるべく、絶賛実装中です！**ご期待くださいませ。

なお、`dotnet watch` 経由で .NET Hot Reload を使用している場合、ASP.NET Core でホストされた Blazor WebAssembly アプリに変更が適用されるようになりました。また、ブラウザを更新すると、Blazor WebAssembly アプリに変更が再適用されます。

.NET Hot Reload の詳細については、以下のブログ記事で紹介していますので、是非合わせて読んでみてください。

https://aka.ms/build2021-hotreload

以下上記の意訳版

https://qiita.com/uikou/items/4022e31ca14bd90842bb

#Razor におけるジェネリック型制約
Razor で `@typeparam` ディレクティブを使用してジェネリック型パラメータを定義する際に、標準 C# 構文を使用してジェネリック型制約を指定できるようになりました。

```diff_c_sharp
@typeparam TEntity where TEntity : IEntity
```

#Blazor のエラー境界
Blazor のエラー境界は、コンポーネント階層内の例外を処理する便利な方法を提供します。エラー境界を定義するには、新しい　`ErrorBoundary` コンポーネントを使用し、いくつかの既存のコンテンツをラップします。`ErrorBoundary` コンポーネントは、すべてがスムーズに動作するよう、その Child コンテンツをレンダリングします。未ハンドリングの例外がスローされた場合、`ErrorBoundary` はエラー UI をレンダリングします。

以下の例では、既定の Blazor アプリのレイアウトの本文コンテンツの周りにエラー境界を追加しています。

```diff_html
<div class="main">
    <div class="top-row px-4">
        <a href="https://docs.microsoft.com/aspnet/" target="_blank" rel="noopener">About</a>
    </div>

    <div class="content px-4">
        <ErrorBoundary>
            @Body
        </ErrorBoundary>
    </div>
</div>
```

アプリケーションは以前と同じように機能します。しかし、エラー境界が処理されない例外を処理するようになります。たとえば、`Counter` コンポーネントを更新して、カウントが大きくなりすぎた場合に例外を発生させるようにします。

```diff_c_sharp
private void IncrementCount()
{
    currentCount++;
    if (currentCount > 10)
    {
        throw new InvalidOperationException("Current count is too big!");
    }
}
```

ここで、カウンターを激しくクリックしまくってみますと、処理されない例外が発生します。発生した例外はエラー境界によって処理されます（既定のエラー UI がレンダリングされます）

![VSe](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/error-boundaries-default-ui.png)

既定で `ErrorBoundary` コンポーネントは、そのエラー コンテンツのために `blazor-error-boundary` CSS クラスを持つ空のコンテンツ分割要素 (<div>) をレンダリングします。既定の UI 色、テキスト、アイコンは、アプリ内で CSS を使って定義されるており、自由にカスタマイズすることができます。
また、`ErrorContent` プロパティを設定することで、既定のエラー コンテンツを変更することができます。

```diff_html
<ErrorBoundary>
    <ChildContent>
        @Body
    </ChildContent>
    <ErrorContent>
        <p class="my-error">Nothing to see here right now. Sorry!</p>
    </ErrorContent>
</ErrorBoundary>
```

レイアウトでエラー境界を定義したため、例外が発生すると、どのページに移動してもエラーの内容しか表示されなくなります。
一般的に、エラー境界の範囲はこれよりも狭くすることが望ましいのですが、エラー境界の `Recover` メソッドを呼び出すことで、その後のページ移動でエラー境界を非エラー状態にリセットすることができます。

```diff_c_sharp
...
<ErrorBoundary @ref="errorBoundary">
    @Body
</ErrorBoundary>
...

@code {
    ErrorBoundary errorBoundary;

    protected override void OnParametersSet()
    {
        // On each page navigation, reset any error state
        errorBoundary?.Recover();
    }
}
```

#Blazor WebAssembly ahead-of-time (AOT) コンパイル
Blazor WebAssembly は、AOT（ahead-of-time）コンパイルをサポートしています。AOT コンパイルでは、.NET コードを直接WebAssembly にコンパイルすることで、実行時のパフォーマンスを大幅に向上させることができます。

現在の Blazor WebAssembly アプリは、WebAssembly に実装された .NET の中間言語 (Intermediate Language = IL) インタプリタを使用して実行されます。.NET コードはインタプリタによって逐次解釈されながら実行されますので、WebAssembly 上で実行される .NET コードは、通常の.NET ランタイム上で実行される場合よりもはるかに遅くなってしまうことになります。そこで、.NET WebAssembly AOT コンパイルは、.NET コードを直接 WebAssembly にコンパイルすることで、このパフォーマンスの問題を解決しました。

例えば、下のクリップは、同じ Blazor WebAssembly アプリを使って基本的な画像編集を行った場合の例です。最初にインタプリタを使用し、次にAOTコンパイルを行い、比較しています。結果はインタプリタより、AOT コンパイル版は 5 倍以上も高速に動作していることがわかります。このように、Blazor WebAssembly アプリを AOT コンパイルすることによるパフォーマンスの向上は、特に CPU 負荷の高いタスクで劇的な効果をもたらすことを期待できます。

![blazor](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/PictureFixerAOT.gif)

この [PictureFixer](https://aka.ms/picture-fixer) のコードは、GitHub で確認することができます。

https://github.com/SteveSandersonMS/PictureFixer

.NET WebAssembly AOT コンパイルには、追加のビルド ツールが必要です。使用するためにはオプションの .NET SDK ワークロードとしてインストールする必要があります。
.NET WebAssembly のビルドツールをインストールするには、昇格したコマンドプロンプトから次のコマンドを実行します。

```
dotnet workload install microsoft-net-sdk-blazorwebassembly-aot
```

Blazor の WebAssembly プロジェクトで WebAssembly の AOT コンパイルを有効にするには、プロジェクト ファイルに以下のプロパティを追加します。

`<RunAOTCompilation>true</RunAOTCompilation>`

AOT がアプリを WebAssembly にコンパイルするには、アプリをパブリッシュします。Release 設定を使用してパブリッシュすると、.NET IL リンクも実行され、パブリッシュされたアプリのサイズが小さくなります。

```
dotnet publish -c Release
```

WebAssembly AOT のコンパイルは、プロジェクトがパブリッシュされたときにのみ行われます。開発中にプロジェクトが実行されるときには使用されません。これは、WebAssembly AOT のコンパイルに時間がかかるためです。WebAssembly AOT コンパイルのためのビルド時間を短縮することに私たちは取り組んでいます。

AOT コンパイルされた Blazor WebAssembly アプリのサイズは、一般的に .NET IL のままのアプリよりも大きくなります。
私たちの検証によれば、AOT コンパイルされた Blazor WebAssembly アプリは、特定のアプリにもよるものの、約 2 倍ほど大きくなります。これは、WebAssembly の AOT コンパイルを使用すると、ロードタイムのパフォーマンスとランタイムのパフォーマンスがトレードオフとなることを意味します。
では、トレードオフの価値があるかどうか。それは、アプリの要件によって異なってくるでしょう。特に CPU 負荷の高い Blazor WebAssembly アプリは、AOT コンパイルの恩恵を最も受けることができるといえます。
#.NET MAUI Blazor アプリ
Blazor では、.NET でクライアント サイドの Web UI を構築することができますが、Web プラットフォームが提供するもの以上のものが必要な場合や、デバイスのネイティブ機能に完全にアクセスする必要がある場合などもあるでしょう。
そこで、.NET MAUI の出番です。Blazor コンポーネントを .NET MAUI アプリでホストし、Web UI を使用してクロス プラットフォームのネイティブ アプリを構築することができるのです。
コンポーネントは .NET プロセス内でネイティブに実行され、ローカル Interop チャネルを使用し、Web UI を埋め込み Web View コントロールにレンダリングします。このハイブリッドなアプローチは、ネイティブとウェブの長所を兼ね備えているといえます。
コンポーネントは、.NET プラットフォームを通じてネイティブ機能にアクセスし、標準的な Web UI をレンダリングします。
.NET MAUI Blazor アプリは、.NET MAUI が可能な場所（Windows、Mac、iOS、Android）であればどこでも実行できますが、.NET 6 では主にデスクトップのシナリオに焦点を当てています。

.NET MAUI Blazor アプリを作成するには、まず開発マシンで .NET MAUI をセットアップする必要があります。最も簡単な方法は、`maui-check` ツールを使用することです。

`maui-check` ツールのインストールは以下を実行します。

```
dotnet tool install -g Redth.Net.Maui.Check
```

その後、`maui-check` を実行し、.NET MAUI のツールと依存関係を取得します。
.NET MAUI の使用開始に関する追加情報については、以下 wiki を参照してください。

https://github.com/dotnet/maui/wiki/Getting-Started

ここまでのインストールを完了したら、新しいプロジェクト テンプレートを使って、.NET MAUI Blazor アプリを作成します。

```
dotnet new maui-blazor -o MauiBlazorApp
```

あるいは、Visual Studio 上から作成することも可能です。

![VSC5](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/new-maui-blazor-app.png)

.NET MAUI Blazor　アプリは、`BlazorWebView` コントロールを使用して Blazor コンポーネントを埋め込み Web ビューにレンダリングする.NET MAUI アプリです。
アプリのコードとロジックは *MauiApp* プロジェクトにあり、Android、iOS、Mac Catalyst のマルチ ターゲットに設定されています。

*MauiApp.WinUI3* プロジェクトは Windows 用のビルドに使用され、*MauiApp.WinUI3 (Package)* プロジェクトは Windows 用のMSIX パッケージの生成に使用されます。最終的には、Windows のサポートをメインのアプリケーション プロジェクトに統合することが望ましいのですが、現状としてはそれぞれに対し、別々のプロジェクトが必要です。

`BlazorWebView` コントロールは、MauiApp プロジェクトの*MainPage.xaml* で設定されています。

```diff_html
<b:BlazorWebView HostPage="wwwroot/index.html">
    <b:BlazorWebView.RootComponents>
        <b:RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
    </b:BlazorWebView.RootComponents>
</b:BlazorWebView>
```

アプリ ルートの Blazor コンポーネントは *Main.razor* にあります。残りの Blazor コンポーネントは、*Pages* と *Shared* ディレクトリにあります。
これらのコンポーネントは、既定の Blazor テンプレートで使用されているものと同じです。既存の Blazor コンポーネントは、コードをアプリ内に移動するか、コンポーネントを含む既存のクラスライブラリやパッケージを参照することで、アプリ内で変更せずに使用することができます。アプリの静的な Web アセットは wwwroot フォルダにあります。

###Windows 用のアプリケーションを構成する
Windows をターゲットにしたアプリケーションの場合、Visual Studio を使ってビルドと実行を行う必要があります。スタートアッププロジェクトとして、*MauiBlazorApp.WinUI3 (Package)* プロジェクトを選択します。

![vsc6](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/maui-blazor-winui-startup-project.png)

ターゲットプラットフォームには x64 を選択します。

![vsc7](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/select-x64-platform.png)

`F5` または `Ctrl + F5` を押すと、WinUI を使って Windows のネイティブ デスクトップ アプリケーションとして実行できます。

![vsc8](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/maui-blazor-winui.png)

###Android
Android で実行するアプリケーションを開発し、実行するには、まず、Android SDK またはAndroid Device Manager を使って Android エミュレーターを起動します。

次に、以下のコマンドを使ってCLIからアプリを実行します。

```
dotnet build MauiBlazorApp -t:Run -f net6.0-android
```

Visual Studio から Android 上で実行するには、起動プロジェクトとして MauiBlazorApp プロジェクトを選択します。

![vsc9](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/maui-blazor-startup-project.png)

次に、「実行」ボタンをドロップダウンし、メニューから、ターゲット フレームワークとして「net6.0-android」を選択します。

![vsc10](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/maui-blazor-select-android.png)

`F5` または `Ctrl + F5` を押して、Android エミュレータを使ってアプリを実行することができます。

![vsc11](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/maui-blazor-android.png)

#iOS および Mac Catalyst
現在のところ、Windows の開発環境から iOS や Mac Catalyst 用のアプリを実行することはできませんため、iOS または Mac Catalyst 用のアプリを実行するには、Big Sur が動作する macOS 開発環境を用意する必要があります。

ただし、.NET MAUI では、接続された Mac のビルド エージェントを使用した iOS アプリの実行や、Hot restart を使用した接続デバイスでの実行がサポートされることが期待されています。

iOS や Mac Catalyst 用のアプリを実行するには、以下のコマンドを使用します。

```
dotnet build MauiBlazorApp -t:Run -f net6.0-ios
dotnet build MauiBlazorApp -t:Run -f net6.0-maccatalyst
```

![VSc12](https://devblogs.microsoft.com/aspnet/wp-content/uploads/sites/16/2021/05/maui-blazor-ios-mac.png)

**!注意! このリリースでは、.NET MAUI Blazorアプリにいくつかの既知の制限があります。**
コンポーネントにスコープされた CSS ファイル（.razor.css）は、メインの .NET MAUI プロジェクトではまだ機能していません。これは将来のアップデートで修正される予定です。
.NET 6 Preview 4 での .NET MAUI の新機能については以下をご覧ください。

https://devblogs.microsoft.com/dotnet/announcing-net-maui-preview-4

#その他のパフォーマンス改善事項
ASP.NET Core のパフォーマンスを継続的に向上させる一環として、スタック全体で割り当てを減らし、パフォーマンスを向上させるためのさまざまな変更を行いました。

* [Non-allocating app.Use() extension method](https://github.com/dotnet/aspnetcore/pull/31784)
    * `next()` に `context` を渡すことを必要とする `app.Use` の新しいオーバーロードがあります。これにより、他のオーバーロードを使用する際に必要となる、リクエストごとの 2 つの内部割り当てを削減しました。
* [Cookie への割り当てを減らしました](https://github.com/dotnet/aspnetcore/pull/31258)
* [HttpSysServer に LoggerMessage.Define を使用するようにしました (Community Contribution)](https://github.com/dotnet/aspnetcore/pull/31333)
    * ILogger 拡張メソッドの使用を、`HttpSysServer` のLoggerMessage.Define() の呼び出しに置き換えました。
* [SocketConnection の接続ごとのオーバーヘッドを削減しました](https://github.com/dotnet/aspnetcore/pull/31308)
    * `SocketConnection` のオーバーヘッドを ～30% 削減しました。
* [ジェネリック タイプにおけるロギング デリゲートの削除により、割り当て処理を削減しました](https://github.com/dotnet/aspnetcore/issues/31340)
* よく使われる機能へのアクセスの高速化
    * 一般的に使用される機能（`IHttpRequestFeature`、`IHttpResponseFeature`、`IHttpResponseBodyFeature`、`IRouteValuesFeatures`、および `IEndpointFeature`）へのアクセスを ～50% 向上させました。
* [事前に割り当てられたブロックにない既知のヘッダーに対して Intern されたヘッダー名を使用します](https://github.com/dotnet/aspnetcore/pull/31311)
    * よく知られているヘッダーについては、複数の接続で文字列が重複しないように、値を Intern された文字列に交換しています。
* [Kestrel での HttpProtocol CancellationTokenSource の再利用](https://github.com/dotnet/aspnetcore/pull/31466)
    * [CancellationTokenSource の新しい TryReset() メソッド](https://github.com/dotnet/runtime/issues/48492/)を使用して、キャンセルされていないトークンを再利用します。
* [DefaultHubDispatcher.Invoke() における の割り当てを避ける](https://github.com/dotnet/aspnetcore/pull/31641)
    * closure の割り当てを避けるために、ローカルの Static 関数に引数を介して状態を渡します。
* [Hub Method の呼び出しごとではなく HubCallerClient を接続ごとに一度だけ割り当てます](https://github.com/dotnet/aspnetcore/pull/31661)
* [Stream-Item ごとの割り当てではなく、サーバからクライアントへのストリーミングにおいて、StreamItem をストリームごとに一度だけ割り当てます](https://github.com/dotnet/aspnetcore/pull/31660)
* [AdaptiveCapacityDictionary の実装と使用により、最大 4 エントリのディクショナリへのより効率的なアクセスを実現します](https://github.com/dotnet/aspnetcore/pull/31360)

#フィードバック超待ってます！！ (Daniel さんが)
ASP.NET Core in .NET 6 の Preview、いかがでしたでしょうか。ぜひ触ってみて、エンジョイしてください。そして、使ってみてどうだったかお聞かせいただけると嬉しいです。
もし、何か問題などありましたら、GitHub の issues からおしらせください。(訳注 : ...って、[Daniel](https://devblogs.microsoft.com/aspnet/author/danroth27/) さんが言ってるんじゃないかなと思います。)

https://github.com/dotnet/aspnetcore/issues

それでは皆様、ごきげんよう。
(※訳注 : 日本語の文章についてのクレームは [uikou](https://www.linkedin.com/in/uikou/) までご連絡ください…）