次の方法で共有


ASP.NET Core 7.0 の新機能

この記事では、ASP.NET Core 7.0 の最も大きな変更点について説明します。また、関連するドキュメントへのリンクも示します。

ASP.NET Core のレート制限ミドルウェア

Microsoft.AspNetCore.RateLimiting ミドルウェアは、レート制限ミドルウェアです。 アプリでレート制限ポリシーを構成し、エンドポイントにポリシーをアタッチします。 詳細については、「ASP.NET Core でのレート制限ミドルウェア」を参照してください。

DefaultScheme として単一スキームを使用する認証

認証を簡略化する作業の一環として、認証スキームが 1 つだけ登録されている場合、それが自動的に DefaultScheme として使用され、指定する必要はありません。 詳細については、「DefaultScheme」を参照してください。

MVC および Razor ページ

MVC ビューと Razor ページでの null 許容モデルのサポート

null 許容ページまたはビュー モデルがサポートされています。これにより、ASP.NET Core アプリで null 状態のチェックを使用する場合のエクスペリエンスが改善されます。

@model Product?

MVC および API コントローラーで IParsable<T>.TryParse とバインドする

IParsable<TSelf>.TryParse API では、バインディング コントローラー アクションのパラメーター値がサポートされています。 詳細については、「IParsable<T>.TryParse にバインドする」を参照してください。

ASP.NET Core バージョンの 7 より前では、cookie 同意の確認では cookie 値の yes を使用して同意が示されます。 同意を表す値を指定できるようになりました。 たとえば、true の代わりに、yes を使用できます。

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.Configure<CookiePolicyOptions>(options =>
{
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
    options.ConsentCookieValue = "true";
});

var app = builder.Build();

詳細については、「cookie の同意の値のカスタマイズ」を参照してください。

API コントローラー

API コントローラーの DI を使用したパラメーター バインド

API コントローラー アクションのパラメーター バインドでは、型がサービスとして構成されているときに、依存関係の挿入によってパラメーターをバインドします。 つまり、パラメーターに [FromServices] 属性を明示的に適用する必要はなくなりました。 次のコードでは、どちらのアクションでも時刻が返されます。

[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
    public ActionResult GetWithAttribute([FromServices] IDateTime dateTime) 
                                                        => Ok(dateTime.Now);

    [Route("noAttribute")]
    public ActionResult Get(IDateTime dateTime) => Ok(dateTime.Now);
}

自動 DI により、まれに API コントローラー アクション メソッドでも受け入れられる型が DI 内にあるアプリが動作しなくなる可能性があります。 型が DI 内にある、かつ API コントローラー アクションの引数として存在することは一般的ではありません。 パラメーターの自動バインドを無効にするには、DisableImplicitFromServicesParameters を設定します

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddSingleton<IDateTime, SystemDateTime>();

builder.Services.Configure<ApiBehaviorOptions>(options =>
{
    options.DisableImplicitFromServicesParameters = true;
});

var app = builder.Build();

app.MapControllers();

app.Run();

ASP.NET Core 7.0 では、IServiceProviderIsService を使用してアプリの起動時 DI の型を確認し、API コントローラー アクションの引数が DI または他のソースから取得されたかどうかを判断します。

API コントローラー アクション パラメーターのバインディング ソースを推論する新しいメカニズムでは、次の規則を使用します。

  1. 以前に指定された BindingInfo.BindingSource が上書きされることはありません。
  2. DI コンテナーに登録されている複合型パラメーターには、BindingSource.Services が割り当てられます。
  3. DI コンテナーに登録されていない複合型パラメーターには、BindingSource.Body が割り当てられます。
  4. ''任意'' のルート テンプレートでルート値として表示される名前を持つパラメーターには、 が割り当てられます。BindingSource.Path
  5. その他のパラメーターはすべて BindingSource.Query です。

検証エラーでの JSON プロパティ名

既定では、検証エラーが発生すると、モデルの検証によって、プロパティ名をエラー キーとして ModelStateDictionary が生成されます。 シングル ページ アプリなどの一部のアプリでは、Web API から生成された検証エラーに JSON プロパティ名を使用するとメリットがあります。 次のコードでは、SystemTextJsonValidationMetadataProvider を使って JSON プロパティ名を使用するように検証を構成しています。

using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.ModelMetadataDetailsProviders.Add(new SystemTextJsonValidationMetadataProvider());
});

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

次のコードでは、NewtonsoftJsonValidationMetadataProvider を使う場合に を使って JSON プロパティ名を使用するように検証を構成しています。

using Microsoft.AspNetCore.Mvc.NewtonsoftJson;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    options.ModelMetadataDetailsProviders.Add(new NewtonsoftJsonValidationMetadataProvider());
}).AddNewtonsoftJson();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

詳細については、「検証エラーで JSON プロパティ名を使用する」をご覧ください

最小 Api

Minimal API アプリのフィルター

Minimal API のフィルターを使うと、開発者は以下をサポートするビジネス ロジックを実装できます。

  • ルート ハンドラーの前後でコードを実行する。
  • ルート ハンドラーの呼び出し中に指定されたパラメーターの検査と変更。
  • ルート ハンドラーの応答動作のインターセプト。

フィルターは、次のシナリオで役立つことがあります。

  • エンドポイントに送信される要求パラメーターと本文を検証する。
  • 要求と応答に関する情報をログに記録する。
  • サポートされている API バージョンを要求が対象としていることを検証する。

詳細については、「Minimal API アプリのフィルター」を参照してください

ヘッダーとクエリ文字列から配列と文字列値をバインドする

ASP.NET 7 では、クエリ文字列をプリミティブ型の配列、文字列配列、StringValues にバインドすることがサポートされています。

// Bind query string values to a primitive type array.
// GET  /tags?q=1&q=2&q=3
app.MapGet("/tags", (int[] q) =>
                      $"tag1: {q[0]} , tag2: {q[1]}, tag3: {q[2]}");

// Bind to a string array.
// GET /tags2?names=john&names=jack&names=jane
app.MapGet("/tags2", (string[] names) =>
            $"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");

// Bind to StringValues.
// GET /tags3?names=john&names=jack&names=jane
app.MapGet("/tags3", (StringValues names) =>
            $"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");

クエリ文字列またはヘッダー値を複合型の配列にバインドすることは、その型で TryParse が実装されている場合にサポートされます。 詳細については、「ヘッダーとクエリ文字列から配列と文字列値をバインドする」を参照してください。

詳細については、エンドポイントの概要または説明の追加に関するページを参照してください。

要求本文を Stream または PipeReader としてバインドする

ユーザーがデータを処理して次のようにする必要がある場合は、シナリオを効率的にサポートするために、要求本文を Stream または PipeReader としてバインドできます。

  • データを Blob Storage に格納するか、キュー プロバイダーにデータをエンキューします。
  • ワーカー プロセスまたはクラウド関数で、格納されたデータを処理します。

たとえば、データは Azure Queue Storage にエンキューされるか、Azure Blob Storage に格納される場合があります。

詳細については、要求本文を Stream または PipeReader としてバインドする方法に関する記事を参照してください

新しい Results.Stream オーバーロード

基になる HTTP 応答ストリームへのアクセスをバッファーリングなしで行う必要があるシナリオに対応するために、新しい Results.Stream オーバーロードが導入されました。 これらのオーバーロードにより、API でデータを HTTP 応答ストリームにストリーミングするケース (Azure Blob Storage など) も改善されます。 次の例では、ImageSharp を使って、指定した画像の縮小サイズを返します。

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing;

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/process-image/{strImage}", (string strImage, HttpContext http, CancellationToken token) =>
{
    http.Response.Headers.CacheControl = $"public,max-age={TimeSpan.FromHours(24).TotalSeconds}";
    return Results.Stream(stream => ResizeImageAsync(strImage, stream, token), "image/jpeg");
});

async Task ResizeImageAsync(string strImage, Stream stream, CancellationToken token)
{
    var strPath = $"wwwroot/img/{strImage}";
    using var image = await Image.LoadAsync(strPath, token);
    int width = image.Width / 2;
    int height = image.Height / 2;
    image.Mutate(x =>x.Resize(width, height));
    await image.SaveAsync(stream, JpegFormat.Instance, cancellationToken: token);
}

詳細については、ストリームの例に関する記事をご覧ください。

Minimal API における型指定された結果

.NET 6 では、IResult インターフェイスが導入されたことで、返されたオブジェクトを HTTP 応答にシリアル化する JSON の暗黙的なサポートを利用しない Minimal API から返される値を表すことができます。 異なる型の応答を表すさまざまな オブジェクトを作成するには、静的な IResult クラスを使います。 たとえば、応答状態コードを設定したり、別の URL にリダイレクトしたりします。 ただし、これらのメソッドから返される IResult 実装フレームワーク型は内部的なものであるため、単体テストのメソッドから返される特定の IResult 型を確認することは困難です。

.NET 7 では、IResult を実装する型はパブリックであり、テスト時に型のアサーションを使用できます。 次に例を示します。

[TestClass()]
public class WeatherApiTests
{
    [TestMethod()]
    public void MapWeatherApiTest()
    {
        var result = WeatherApi.GetAllWeathers();
        Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
    }      
}

最小ルート ハンドラーの単体テストの容易性の向上

IResult 実装の種類が Microsoft.AspNetCore.Http.HttpResults 名前空間で一般に使用できるようになりました。 IResult 実装の種類を使用すると、ラムダの代わりに名前付きメソッドを使用するときに、最小限のルート ハンドラーの単体テストを行うことができます。

次のコードでは、Ok<TValue> クラスを使用します。

[Fact]
public async Task GetTodoReturnsTodoFromDatabase()
{
    // Arrange
    await using var context = new MockDb().CreateDbContext();

    context.Todos.Add(new Todo
    {
        Id = 1,
        Title = "Test title",
        Description = "Test description",
        IsDone = false
    });

    await context.SaveChangesAsync();

    // Act
    var result = await TodoEndpointsV1.GetTodo(1, context);

    //Assert
    Assert.IsType<Results<Ok<Todo>, NotFound>>(result);

    var okResult = (Ok<Todo>)result.Result;

    Assert.NotNull(okResult.Value);
    Assert.Equal(1, okResult.Value.Id);
}

詳細については、「IResult 実装の種類」を参照してください。

新しい HttpResult インターフェイス

Microsoft.AspNetCore.Http 名前空間の次のインターフェイスには、実行時に IResult 型を検出する方法が用意されています。これはフィルター実装の一般的なパターンです。

詳細については、「IHttpResult インターフェイス」を参照してください。

Mminimal API に対する OpenAPI の機能強化

Microsoft.AspNetCore.OpenApi NuGet パッケージ

Microsoft.AspNetCore.OpenApi パッケージを使用すると、エンドポイントの OpenAPI 仕様との対話が可能になります。 このパッケージは、Microsoft.AspNetCore.OpenApi パッケージで定義されている OpenAPI モデルと、Minimal API で定義されているエンドポイント間のリンクとして機能します。 このパッケージには、エンドポイントのパラメーター、応答、メタデータを調べて、エンドポイントを記述するために使用される OpenAPI 注釈の種類を構築する API が用意されています。

app.MapPost("/todoitems/{id}", async (int id, Todo todo, TodoDb db) =>
{
    todo.Id = id;
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi();

パラメーターを指定して WithOpenApi を呼び出す

WithOpenApi メソッドには、OpenAPI 注釈の変更に使用できる関数を指定できます。 たとえば、次のコードでは、エンドポイントの最初のパラメーターに記述が追加されています。

app.MapPost("/todo2/{id}", async (int id, Todo todo, TodoDb db) =>
{
    todo.Id = id;
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi(generatedOperation =>
{
    var parameter = generatedOperation.Parameters[0];
    parameter.Description = "The ID associated with the created Todo";
    return generatedOperation;
});

エンドポイントの説明と概要を指定する

最小限の API では、OpenAPI 仕様の生成に関する説明と概要を使用した操作に注釈を付ける機能がサポートされるようになりました。 拡張メソッド WithDescriptionWithSummary を呼び出すか、または属性 [EndpointDescription][EndpointSummary] を使用することができます。

詳細については、Minimal API アプリでの OpenAPI に関する記事を参照してください

IFormFile と IFormFileCollection を使用したファイルのアップロード

Minimal API で、IFormFileIFormFileCollection でのファイルのアップロードをサポートするようになりました。 次のコードでは、IFormFileIFormFileCollection を使用して、ファイルをアップロードしています。

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapPost("/upload", async (IFormFile file) =>
{
    var tempFile = Path.GetTempFileName();
    app.Logger.LogInformation(tempFile);
    using var stream = File.OpenWrite(tempFile);
    await file.CopyToAsync(stream);
});

app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
    foreach (var file in myFiles)
    {
        var tempFile = Path.GetTempFileName();
        app.Logger.LogInformation(tempFile);
        using var stream = File.OpenWrite(tempFile);
        await file.CopyToAsync(stream);
    }
});

app.Run();

承認ヘッダークライアント証明書、または cookie ヘッダーを使用した認証されたファイルのアップロード要求がサポートされています。

偽造防止の組み込みでのサポートはありません。 ただし、IAntiforgery サービスを使用して実装することはできます。

[AsParameters] 属性では、引数リストでのパラメーターのバインドが可能です

[AsParameters] 属性では、引数リストでのパラメーターのバインドが可能です。 詳細については、[AsParameters] を使用した引数リストでのパラメーター バインドに関する説明を参照してください。

Minimal API と API コントローラー

新しい問題の詳細サービス

問題の詳細サービスは IProblemDetailsService インターフェイスを実装し、HTTP API の問題の詳細の作成がサポートされます。

詳細については、問題の詳細サービスに関する記事を参照してください。

ルート グループ

MapGroup 拡張メソッドは、共通のプレフィックスを持つエンドポイントのグループを整理するのに役立ちます。 これにより、繰り返しのコードを減らし、RequireAuthorizationを追加する WithMetadata のようなメソッドを 1 回呼び出すだけで、エンドポイントのグループ全体をカスタマイズできます。

たとえば、次のコードにより、2 つの似たエンドポイント グループが作成されます。

app.MapGroup("/public/todos")
    .MapTodosApi()
    .WithTags("Public");

app.MapGroup("/private/todos")
    .MapTodosApi()
    .WithTags("Private")
    .AddEndpointFilterFactory(QueryPrivateTodos)
    .RequireAuthorization();


EndpointFilterDelegate QueryPrivateTodos(EndpointFilterFactoryContext factoryContext, EndpointFilterDelegate next)
{
    var dbContextIndex = -1;

    foreach (var argument in factoryContext.MethodInfo.GetParameters())
    {
        if (argument.ParameterType == typeof(TodoDb))
        {
            dbContextIndex = argument.Position;
            break;
        }
    }

    // Skip filter if the method doesn't have a TodoDb parameter.
    if (dbContextIndex < 0)
    {
        return next;
    }

    return async invocationContext =>
    {
        var dbContext = invocationContext.GetArgument<TodoDb>(dbContextIndex);
        dbContext.IsPrivate = true;

        try
        {
            return await next(invocationContext);
        }
        finally
        {
            // This should only be relevant if you're pooling or otherwise reusing the DbContext instance.
            dbContext.IsPrivate = false;
        }
    };
}
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
    group.MapGet("/", GetAllTodos);
    group.MapGet("/{id}", GetTodo);
    group.MapPost("/", CreateTodo);
    group.MapPut("/{id}", UpdateTodo);
    group.MapDelete("/{id}", DeleteTodo);

    return group;
}

このシナリオでは、Location 結果の 201 Created ヘッダーに相対アドレスを使用できます。

public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
    await database.AddAsync(todo);
    await database.SaveChangesAsync();

    return TypedResults.Created($"{todo.Id}", todo);
}

エンドポイントの最初のグループは、/public/todos のプレフィックスが付いた要求にのみ一致し、認証なしでアクセスできます。 エンドポイントの 2 番目のグループは、/private/todos のプレフィックスが付いた要求にのみ一致し、認証が必要です。

QueryPrivateTodos エンドポイント フィルター ファクトリは、プライベート todo データへのアクセスとその保存を許可するようにルート ハンドラーの TodoDb パラメーターを変更するローカル関数です。

ルート グループでは、ルート パラメーターと制約を含む入れ子になったグループと複雑なプレフィックス パターンもサポートされます。 次の例で、user グループにマップされたルート ハンドラーは、外部グループ プレフィックスで定義されている {org} および {group} ルート パラメーターをキャプチャできます。

プレフィックスは空にすることもできます。 これは、ルート パターンを変更せずにエンドポイントのグループにエンドポイント メタデータまたはフィルターを追加する場合に役立ちます。

var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");

フィルターまたはメタデータをグループに追加すると、内部グループまたは特定のエンドポイントに追加された可能性のある追加のフィルターまたはメタデータを追加する前に各エンドポイントに個別に追加する場合と同じように動作します。

var outer = app.MapGroup("/outer");
var inner = outer.MapGroup("/inner");

inner.AddEndpointFilter((context, next) =>
{
    app.Logger.LogInformation("/inner group filter");
    return next(context);
});

outer.AddEndpointFilter((context, next) =>
{
    app.Logger.LogInformation("/outer group filter");
    return next(context);
});

inner.MapGet("/", () => "Hi!").AddEndpointFilter((context, next) =>
{
    app.Logger.LogInformation("MapGet filter");
    return next(context);
});

上記の例では、外部フィルターは、2 番目に追加された場合でも、内部フィルターの前に受信要求をログに記録します。 フィルターは異なるグループに適用されているため、互いが相対的に追加された順序は関係ありません。 同じグループまたは特定のエンドポイントに適用されている場合、追加される順序フィルターは重要です。

/outer/inner/ に対する要求によって、以下のものがログに記録されます。

/outer group filter
/inner group filter
MapGet filter

gRPC

JSON コード変換

gRPC JSON コード変換は、gRPC サービス用の RESTful JSON API を作成する ASP.NET Core 向けの拡張機能です。 gRPC JSON コード変換によって、次のことができます。

  • 使い慣れた HTTP の概念を使ってアプリで gRPC サービスを呼び出す。
  • ASP.NET Core gRPC アプリで、機能をレプリケートせずに gRPC API と RESTful JSON API の両方をサポートする。
  • Swashbuckle と統合することで、コード変換された RESTful API から OpenAPI を生成するための試験的なサポート。

詳細については、「ASP.NET Core gRPC アプリの gRPC JSON でのコード変換」および「gRPC JSON コード変換 ASP.NET Core アプリで OpenAPI を使用する」をご覧ください。

ASP.NET Core の gRPC 正常性チェック

gRPC 正常性チェック プロトコルは、gRPC サーバー アプリの正常性を報告するための標準です。 アプリは、正常性チェックを gRPC サービスとして公開します。 通常、アプリの状態を確認するために、外部の監視サービスと併用されます。

gRPC ASP.NET Core では、Grpc.AspNetCore.HealthChecks パッケージを使った gRPC 正常性チェックの組み込みサポートが追加されています。 .NET 正常性チェックの結果は呼び出し元に報告されます。

詳細については、「ASP.NET Core の gRPC 正常性チェック」を参照してください。

呼び出しの資格情報のサポートを強化

呼び出しの資格情報は、認証トークンをサーバーに送信するように gRPC クライアントを構成するための推奨される方法です。 gRPC クライアントでは、呼び出しの資格情報を使いやすくするための 2 つの新機能がサポートされています。

  • プレーンテキスト接続を使った呼び出しの資格情報のサポート。 以前は、gRPC 呼び出しで呼び出しの資格情報が送信されるのは、接続が TLS で保護されていた場合のみでした。 GrpcChannelOptions の新しい設定 (UnsafeUseInsecureChannelCallCredentials と呼ばれます) を使用すると、この動作をカスタマイズできます。 接続を TLS で保護しないことには、セキュリティ上の影響があります。
  • AddCallCredentials という新しいメソッドが gRPC クライアント ファクトリで使用できます。 AddCallCredentials は、gRPC クライアントの呼び出しの資格情報を簡単に構成する方法であり、依存関係の挿入 (DI) と適切に統合できます。

次のコードは、Authorization メタデータを送信するように gRPC クライアント ファクトリを構成します。

builder.Services
    .AddGrpcClient<Greeter.GreeterClient>(o =>
    {
       o.Address = new Uri("https://localhost:5001");
    })
    .AddCallCredentials((context, metadata) =>
    {
       if (!string.IsNullOrEmpty(_token))
       {
          metadata.Add("Authorization", $"Bearer {_token}");
       }
       return Task.CompletedTask;
    });

詳細については、gRPC クライアント ファクトリを使用したベアラー トークンの構成に関する記事を参照してください。

SignalR

クライアント結果

サーバーは、クライアントからの結果の要求をサポートするようになりました。 これには、サーバーは ISingleClientProxy.InvokeAsync を使用し、クライアントはその .On ハンドラーから結果を返す必要があります。 厳密に型指定されたハブは、インターフェイス メソッドから値を返すこともできます。

詳しくは、「クライアント結果」をご覧ください。

SignalR ハブ メソッドの依存関係の挿入

SignalR ハブ メソッドでは、依存関係の挿入 (DI) を介したサービスの挿入がサポートされるようになりました。

ハブ コンストラクターには DI からのサービスをパラメーターとして指定することができ、それはクラスのプロパティに格納してハブ メソッドで使用できます。 詳細については、「ハブにサービスを挿入する」を参照してください

Blazor

場所変更イベントとナビゲーション状態を処理する

.NET 7 では、Blazor で場所変更イベントとナビゲーション状態の維持がサポートされます。 これにより、保存されていない作業についてユーザーに警告したり、ユーザーがページ ナビゲーションを実行するときに関連するアクションを実行したりできます。

詳しくは、ルーティングとナビゲーションに関する記事の、次のセクションをご覧ください。

空の Blazor プロジェクト テンプレート

Blazor には、空白のスレートから開始するための 2 つの新しいプロジェクト テンプレートがあります。 新しい Blazor Server App Empty プロジェクト テンプレートと Blazor WebAssembly App Empty プロジェクト テンプレートは、空ではないプロジェクト テンプレートと似ていますが、コード例がありません。 これらの空のテンプレートには基本的なホーム ページのみが含まれており、ブートストラップを削除して、別の CSS フレームワークから始めることができます。

詳細については、次の記事をご覧ください。

Blazor カスタム要素

Microsoft.AspNetCore.Components.CustomElements パッケージを使用すると、 を使用してBlazorを構築できます。

詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。

バインド修飾子 (@bind:after@bind:get@bind:set)

重要

@bind:after / @bind:get / @bind:set 機能は、現時点でさらに更新プログラムを受け取っています。 最新の更新プログラムを利用するには、最新の SDK がインストールされていることを確認してください。

イベント コールバック パラメーター ([Parameter] public EventCallback<string> ValueChanged { get; set; }) の使用はサポートされていません。 代わりに、Action または Task から返されたメソッドを @bind:set/@bind:after に渡します。

詳細については、次のリソースを参照してください。

.NET 7 では、新しい @bind:after 修飾子を使用して、バインド イベントが完了した後に非同期ロジックを実行できます。 次の例では、検索テキストへの変更が検出された後に、非同期メソッド PerformSearch が自動的に実行されます。

<input @bind="searchText" @bind:after="PerformSearch" />

@code {
    private string searchText;

    private async Task PerformSearch()
    {
        ...
    }
}

.NET 7 では、コンポーネント パラメーターのバインドの設定も、以前より簡単になっています。 コンポーネントでは、パラメーターのペアを定義することで、双方向のデータ バインディングをサポートできます。

  • @bind:get: バインドする値を指定します。
  • @bind:set: 値が変更されたときのコールバックを指定します。

@bind:get 修飾子と @bind:set 修飾子は常に一緒に使用されます。

例 :

@* Elements *@

<input type="text" @bind="text" @bind:after="() => { }" />

<input type="text" @bind:get="text" @bind:set="(value) => { }" />

<input type="text" @bind="text" @bind:after="AfterAsync" />

<input type="text" @bind:get="text" @bind:set="SetAsync" />

<input type="text" @bind="text" @bind:after="() => { }" />

<input type="text" @bind:get="text" @bind:set="(value) => { }" />

<input type="text" @bind="text" @bind:after="AfterAsync" />

<input type="text" @bind:get="text" @bind:set="SetAsync" />

@* Components *@

<InputText @bind-Value="text" @bind-Value:after="() => { }" />

<InputText @bind-Value:get="text" @bind-Value:set="(value) => { }" />

<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />

<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />

<InputText @bind-Value="text" @bind-Value:after="() => { }" />

<InputText @bind-Value:get="text" @bind-Value:set="(value) => { }" />

<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />

<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />

@code {
    private string text = "";

    private void After(){}
    private void Set() {}
    private Task AfterAsync() { return Task.CompletedTask; }
    private Task SetAsync(string value) { return Task.CompletedTask; }
}

InputText コンポーネントについて詳しくは、「ASP.NET Core Blazor の入力コンポーネント」を参照してください。

ホット リロードの機能強化

.NET 7 では、ホット リロードのサポートに次のものが含まれます。

  • コンポーネントは、値が削除されたときにパラメーターを既定値にリセットします。
  • Blazor WebAssembly $
    • 新しい型を追加します。
    • 入れ子になったクラスを追加します。
    • 既存の型に静的メソッドとインスタンス メソッドを追加します。
    • 既存の型に静的フィールドと静的メソッドを追加します。
    • 既存のメソッドに静的ラムダを追加します。
    • 既に this をキャプチャした既存のメソッドに this をキャプチャするラムダを追加します。

Blazor WebAssembly での MSAL を使用した動的認証要求

.NET 7 の新機能として、Blazor WebAssembly では、高度な認証シナリオを処理するためのカスタム パラメーターを使用して、実行時に動的認証要求を作成することができます。

詳細については、次の記事をご覧ください。

Blazor WebAssembly のデバッグの機能強化

Blazor WebAssembly のデバッグについては、次の機能強化が加えられています。

  • ユーザー コードからではない型メンバーを表示または非表示にする、[マイ コードのみ] 設定のサポート。
  • 多次元配列の検査のサポート。
  • 呼び出し履歴で、非同期メソッドについて正しい名前が表示されるようになりました。
  • 式の評価が改善されました。
  • 派生メンバーに対する new キーワードの正しい処理。
  • System.Diagnostics でのデバッガー関連属性のサポート。

WebAssembly での System.Security.Cryptography のサポート

.NET 6 では、WebAssembly での実行時にハッシュ アルゴリズムの SHA ファミリがサポートされていました。 .NET 7 では、(可能な場合に) SubtleCrypto を利用することでより多くの暗号化アルゴリズムに対応できるようになり、SubtleCrypto を使用できない場合には .NET 実装にフォールバックできるようになりました。 .NET 7 の WebAssembly では、次のアルゴリズムがサポートされています。

  • SHA1
  • SHA256
  • SHA384
  • SHA512
  • HMACSHA1
  • HMACSHA256
  • HMACSHA384
  • HMACSHA512
  • AES-CBC
  • PBKDF2
  • HKDF

詳しくは、「browser-wasm をターゲットとする開発者は Web Crypto API を使用できます (dotnet/runtime #40074)」をご覧ください。

カスタム検証属性にサービスを挿入する

カスタム検証属性にサービスを挿入できるようになりました。 Blazor は、ValidationContext をサービス プロバイダーとして使用できるように設定します。

詳細については、「ASP.NET Core Blazor のフォーム検証」を参照してください。

Input* EditContext / の外部にある EditForm コンポーネント

組み込みの入力コンポーネントが、Razor コンポーネント マークアップ内のフォームの外部でサポートされるようになりました。

詳細については、「ASP.NET Core Blazor の入力コンポーネント」を参照してください。

プロジェクト テンプレートの変更

.NET 6 が昨年リリースされたとき、_Host ページ (Pages/_Host.chstml) の HTML マークアップは、.NET 6 の _Host プロジェクト テンプレート内で _Layout ページと新しい Pages/_Layout.chstml ページ (Blazor Server) の間で分割されました。

.NET 7 では、HTML マークアップがプロジェクト テンプレート内で _Host ページと再結合されました。

Blazor プロジェクト テンプレートにはいくつかの追加の変更が加えられました。 テンプレートに対するすべての変更の一覧をこのドキュメントで示すことはできません。 すべての変更を導入するためにアプリを .NET 7 に移行するには、「ASP.NET Core 6.0 から 7.0 への移行」を参照してください。

試験的な QuickGrid コンポーネント

この新しい QuickGrid コンポーネントは、最も一般的な要件に対応した便利なデータ グリッド コンポーネントを提供するもので、Blazor データ グリッド コンポーネントを構築するあらゆるユーザーのための、参照アーキテクチャとパフォーマンス ベースラインとして提供されるものです。

詳細については、ASP.NET Core Blazor 'QuickGrid' コンポーネントを参照してください。

ライブ デモ: Blazor サンプル アプリの QuickGrid

仮想化の機能強化

.NET 7 での仮想化の機能強化:

  • Virtualize コンポーネントでは、overflow-y: scroll が適用された他の要素を使用する代わりに、ドキュメント自体をスクロール ルートとして使用することができます。
  • 特定の子タグ名を必要とする要素内に Virtualize コンポーネントが配置されている場合、SpacerElement を使用すると、仮想化スペーサー タグ名を取得または設定できます。

詳しくは、仮想化に関する記事の、次のセクションをご覧ください。

MouseEventArgs の更新

MovementXMovementYMouseEventArgs が追加されました。

詳細については、「ASP.NET Core Blazor のイベント処理」を参照してください。

新しい Blazor の読み込みページ

Blazor WebAssembly プロジェクト テンプレートには、アプリの読み込みの進行状況を示す新しい読み込み UI があります。

詳しくは、「ASP.NET Core Blazor の起動」をご覧ください。

Blazor WebAssembly での認証の診断の改善

Blazor WebAssembly アプリでの認証の問題を診断するために、詳細なログ記録を使用できます。

詳しくは、「ASP.NET Core Blazor のログ」をご覧ください。

WebAssembly での JavaScript 相互運用

JavaScript [JSImport]/[JSExport] 相互運用 API は、Blazor WebAssembly および JavaScript ベースのアプリで .NET を使用するための新しい低レベル メカニズムです。 この新しい JavaScript 相互運用機能を使用すると、.NET WebAssembly ランタイムを使用して JavaScript から .NET コードを呼び出し、Blazor UI コンポーネント モデルに依存することなく .NET から JavaScript 機能を呼び出すことができます。

詳細情報:

認証状態プロバイダーの条件付き登録

.NET 7 のリリース以前は、AuthenticationStateProvider はサービス コンテナーで AddScoped を使って登録されていました。 これにより、カスタム実装を提供するときにサービス登録の特定の順序が強制されるため、アプリのデバッグが困難になっていました。 時間の経過に伴う内部フレームワークの変化によって、AuthenticationStateProviderAddScoped に登録する必要はなくなりました。

開発者コードで、認証状態プロバイダーのサービス登録に次の変更を加えてください。

- builder.Services.AddScoped<AuthenticationStateProvider, ExternalAuthStateProvider>();
+ builder.Services.TryAddScoped<AuthenticationStateProvider, ExternalAuthStateProvider>();

上記の例では、ExternalAuthStateProvider が開発者のサービス実装です。

.NET WebAssembly ビルド ツールの機能強化

パフォーマンスの向上と例外の処理に役立つ、.NET 7 の wasm-tools ワークロードの新機能:

詳細については、「ASP.NET Core Blazor WebAssembly ビルド ツールと Ahead-Of-Time (AOT) コンパイル」を参照してください。

Blazor Hybrid

外部 URL

ブラウザーで外部 Web ページを開くことを許可するオプションが追加されました。

詳細については、「ASP.NET Core の Blazor Hybrid ルーティングとナビゲーション」を参照してください。

セキュリティ

Blazor Hybrid のセキュリティ シナリオに関する新しいガイダンスが提供されました。 詳細については、次の記事をご覧ください。

パフォーマンス

出力キャッシュ ミドルウェア

出力キャッシュは、Web アプリからの応答を保存して、毎回計算する代わりにキャッシュから提供する、新しいミドルウェアです。 出力キャッシュは、次の点で応答キャッシュとは異なります。

  • キャッシュの動作は、サーバー上で構成できます。
  • キャッシュ エントリは、プログラムによって無効にすることができます。
  • リソース ロックにより、キャッシュ スタンピードthundering herd のリスクが軽減されます。
  • キャッシュの再検証とは、サーバーがキャッシュされた応答本文の代わりに 304 Not Modified HTTP 状態コードを返すことができることを意味します。
  • キャッシュ ストレージ メディアは拡張可能です。

詳細については、キャッシュの概要出力キャッシュ ミドルウェアに関する記事を参照してください。

HTTP/3 の機能強化

このリリースの場合:

  • HTTP/3 が ASP.NET Core で完全にサポートされます。これは実験段階ではなくなりました。
  • Kestrel の HTTP/3 のサポートが向上します。 改善の 2 つの主な領域は、HTTP/1.1 および HTTP/2 との機能パリティと、パフォーマンスです。
  • HTTP/3 での UseHttps(ListenOptions, X509Certificate2) の完全なサポートを提供します。 Kestrel には、Server Name Indication (SNI) へのフックなど、接続証明書を構成するための高度なオプションが用意されています。
  • HTTP.sysIIS での HTTP/3 のサポートが追加されました。

次の例は、SNI コールバックを使用して TLS オプションを解決する方法を示しています。

using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(8080, listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
        listenOptions.UseHttps(new TlsHandshakeCallbackOptions
        {
            OnConnection = context =>
            {
                var options = new SslServerAuthenticationOptions
                {
                    ServerCertificate = 
                         MyResolveCertForHost(context.ClientHelloInfo.ServerName)
                };
                return new ValueTask<SslServerAuthenticationOptions>(options);
            },
        });
    });
});

HTTP/3 の割り当てを減らすために、.NET 7 で大幅な作業が行われました。 それらの機能強化の一部は、次の GitHub PR で確認できます。

HTTP/2 のパフォーマンスの向上

.NET 7 では、Kestrel による HTTP/2 要求の処理方法について重要なアーキテクチャの見直しが導入されています。 HTTP/2 接続がビジー状態の ASP.NET Core アプリでは、CPU 使用率が低下し、スループットが高くなります。

以前は、HTTP/2 多重化の実装は、基になる TCP 接続に書き込むことができる要求を制御する、ロックに依存していました。 スレッドセーフ キューによって、書き込みロックが置き換えられています。 どのスレッドが書き込みロックを使用するかで争う代わりに、要求がキューに入り、専用のコンシューマーがそれらを処理するようになりました。 以前に無駄にされた CPU リソースは、アプリの残りの部分で使用できます。

これらの改善がわかる場所の 1 つは、HTTP/2 を使用する一般的な RPC フレームワークである、gRPC です。 Kestrel + gRPC のベンチマークは、劇的な改善を示しています。

gRPC サーバー ストリーミング パフォーマンス

HTTP/2 フレーム記述コードで変更が行われ、1 つの HTTP/2 接続に複数のストリームがデータを書き込もうとしている場合のパフォーマンスが向上しました。 スレッド プールに TLS 作業がディスパッチされ、他のストリームがデータを書き込むために取得できる書き込みロックがより迅速に解放されるようになりました。 待機時間の短縮により、この書き込みロックの競合が発生した場合のパフォーマンスが、大幅に向上する可能性があります。 この変更により、1 つの接続で 70 ストリーム (TLS を使用) の gRPC ベンチマークでは、1 秒あたりの要求数 (RPS) が約 15% 向上しました。

Http/2 WebSocket のサポート

.NET 7 では、Kestrel、SignalR JavaScript クライアント、SignalR を使用した Blazor WebAssembly に対する WebSocket over HTTP/2 のサポートが導入されました。

WebSocket over HTTP/2 を使用すると、次のような新機能を利用できます。

  • ヘッダーの圧縮。
  • 多重化。サーバーに対して複数の要求を行うときに必要な時間とリソースを削減します。

これらのサポートされている機能は、すべての HTTP/2 対応プラットフォーム上の Kestrel で使用できます。 バージョン ネゴシエーションはブラウザーと Kestrel で自動的に行われるので、新しい API は必要ありません。

詳細については、「Http/2 WebSocket のサポート」を参照してください。

ハイ コア マシンでの Kestrel パフォーマンスの向上

Kestrel では多くの目的で ConcurrentQueue<T> が使用されます。 1 つの目的は、Kestrel の既定のソケット トランスポートで I/O 操作をスケジュールすることです。 関連付けられているソケットに基づいて ConcurrentQueue をパーティション分割すると、競合が減少し、多くの CPU コアを持つマシンのスループットが増加します。

.NET 6 のハイ コア マシンでのプロファイリングでは、Kestrel の他の ConcurrentQueue インスタンスの 1 つ (PinnedMemoryPool でバイト バッファーのキャッシュに使用される Kestrel) で重大な競合が見られました。

.NET 7 では、Kestrel のメモリ プールは I/O キューと同じ方法でパーティション分割されるため、ハイ コア マシンでの競合が大幅に減り、スループットが高くなります。 80 コア ARM64 VM では、TechEmpower プレーンテキスト ベンチマークで 1 秒あたりの応答数 (RPS) が 500% 以上向上しています。 48 コア AMD VM では、HTTPS JSON ベンチマークでほぼ 100% 改善されています。

起動時間を測定する ServerReady イベント

EventSource を使用するアプリでは、起動時間を測定して起動時のパフォーマンスを把握し、最適化できます。 ServerReady の新しい Microsoft.AspNetCore.Hosting イベントは、サーバーが要求に応答する準備ができているポイントを表します。

サーバー

起動時間を測定するための新しい ServerReady イベント

ASP.NET Core アプリのServerReadyを測定するために、 イベントが追加されました。

IIS

IIS でのシャドウ コピー

IIS の ASP.NET Core モジュール (ANCM) にアプリのアセンブリをシャドウ コピーすると、app offline file をデプロイしてアプリを停止するよりも優れたエンド ユーザー エクスペリエンスを実現することができます。

詳細については、IIS のシャドウ コピーに関する記事を参照してください。

その他

Kestrel の完全な証明書チェーンの機能強化

HttpsConnectionAdapterOptions には、X509Certificate2Collection 型の新しい ServerCertificateChain プロパティがあります。これにより、中間証明書を含む完全なチェーンを指定できるため、証明書チェーンを簡単に検証できます。 詳細については、dotnet/aspnetcore#21513 を参照してください。

dotnet watch

dotnet watch のコンソール出力の改善

dotnet watch からのコンソール出力が改善されたことで、ASP.NET Core のログとの整合性が向上し、😮絵文字😍で目立つようになりました。

新しい出力の例を次に示します。

dotnet watch の出力

詳細については、この GitHub pull request を参照してください。

Rude 編集に対して常に再起動するように dotnet watch を構成する

Rude 編集とは、ホット リロードできない編集です。 Rude 編集用のプロンプトなしで常に再起動するように dotnet watch を構成するには、環境変数 DOTNET_WATCH_RESTART_ON_RUDE_EDITtrue に設定します。

開発者例外ページのダーク モード

開発者例外ページにダーク モードのサポートが追加されました。Patrick Westerhoff の協力に感謝します。 ブラウザーでダーク モードをテストするには、開発者ツール ページから、モードをダークに設定します。 たとえば、Firefox の場合:

F12 ツール FF ダーク モード

Chrome の場合:

F12 ツール Chrome ダーク モード

最上位レベルのステートメントの代わりに Program.Main メソッドを使うプロジェクト テンプレートのオプション

.NET 7 テンプレートには、最上位レベルのステートメントを使用せず、namespace クラスで宣言された Main メソッドと Program メソッドを生成するオプションが含まれています。

.NET CLI を使用して、--use-program-main オプションを使います。

dotnet new web --use-program-main

Visual Studio の場合は、プロジェクトの作成時に新しい [最上位レベルのステートメントを使用しない] チェックボックスをオンにします。

チェックボックス

更新された Angular テンプレートと React テンプレート

Angular プロジェクト テンプレートは、Angular 14 に更新されました。 React プロジェクト テンプレートは、React 18.2 に更新されました。

dotnet user-jwts を使用した開発での JSON Web トークンの管理

新しい dotnet user-jwts コマンド ライン ツールでは、アプリ固有のローカル JSON Web トークン (JWT) を作成および管理できます。 詳細については、「dotnet user-jwts を使用した開発での JSON Web トークンの管理」をご覧ください。

W3CLogger での追加の要求ヘッダーのサポート

AdditionalRequestHeaders()W3CLoggerOptions を呼び出して W3C ロガーを使用するときに、ログに記録する追加の要求ヘッダーを指定できるようになりました。

services.AddW3CLogging(logging =>
{
    logging.AdditionalRequestHeaders.Add("x-forwarded-for");
    logging.AdditionalRequestHeaders.Add("x-client-ssl-protocol");
});

詳しくは、「W3CLogger のオプション」をご覧ください。

要求展開

新しい要求展開ミドルウェアは:

  • API エンドポイントが圧縮されたコンテンツを使用して要求を受け入れるようにします。
  • Content-Encoding HTTP ヘッダーを使用して、圧縮されたコンテンツを含む要求を自動的に識別し、展開します。
  • 圧縮された要求を処理するコードを記述する必要がなくなります。

詳細については、要求展開ミドルウェアに関するページを参照してください。