ASP.NET Core 7.0 的新功能

本文強調 ASP.NET Core 7.0 中最重要的變更,其中包含相關檔的連結。

ASP.NET Core 中的速率限制中介軟體

Microsoft.AspNetCore.RateLimiting中介軟體提供速率限制中介軟體。 應用程式會設定速率限制原則,然後將原則附加至端點。 如需詳細資訊,請參閱ASP.NET Core 中的速率限制中介軟體

驗證使用單一配置作為 DefaultScheme

作為簡化驗證的一部分,當只註冊單一驗證配置時,它會自動用來作為 DefaultScheme ,而且不需要指定。 如需詳細資訊,請參閱 DefaultScheme

MVC 和 Razor 頁面

支援 MVC 檢視和 Razor 頁面中可為 Null 的模型

支援可為 Null 的頁面或檢視模型,以改善搭配 ASP.NET Core應用程式使用 Null 狀態檢查時的體驗:

@model Product?

在 MVC 和 API 控制器中系結 IParsable<T>.TryParse

API 支援系 IParsable<TSelf>.TryParse 結控制器動作參數值。 如需詳細資訊,請參閱使用 系 IParsable<T>.TryParse

在 ASP.NET Core 7 之前的版本中,同意驗證會 cookie 使用 cookie 值 yes 來表示同意。 現在您可以指定代表同意的值。 例如,您可以使用 trueyes 而不是 :

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 可能會中斷在 DI 中具有類型的應用程式,該應用程式也會在 API 控制器動作方法中接受。 在 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

JS驗證錯誤中的 ON 屬性名稱

根據預設,當發生驗證錯誤時,模型驗證會產生 ModelStateDictionary 屬性名稱做為錯誤索引鍵的 。 某些應用程式,例如單頁應用程式,可受益于使用 JS ON 屬性名稱來取得從 Web API 產生的驗證錯誤。 下列程式碼會將驗證設定為 JS 使用 SystemTextJsonValidationMetadataProvider ON 屬性名稱:

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();

下列程式碼會設定驗證,以在使用Json.NET時使用 NewtonsoftJsonValidationMetadataProviderJS ON 屬性名稱:

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();

如需詳細資訊,請參閱 在 JS 驗證錯誤中使用 ON 屬性名稱

最小 API

最小 API 應用程式中的篩選

最小的 API 篩選準則可讓開發人員實作支援下列商務邏輯:

  • 在路由處理常式前後執行程式碼。
  • 檢查和修改路由處理常式調用期間提供的參數。
  • 攔截路由處理常式的回應行為。

篩選準則在下列案例中很有説明:

  • 驗證傳送至端點的要求參數和本文。
  • 記錄要求和回應的相關資訊。
  • 驗證要求的目標為支援的 API 版本。

如需詳細資訊,請參閱 基本 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 時,支援將查詢字串或標頭值系結至複雜類型的陣列。 如需詳細資訊,請參閱 從標頭和查詢字串系結陣列和字串值

如需詳細資訊,請參閱 新增端點摘要或描述

將要求本文系結為 StreamPipeReader

要求本文可以系結為 StreamPipeReader ,以有效率地支援使用者必須處理資料的案例,以及:

  • 將資料儲存至 Blob 儲存體,或將資料排入佇列提供者。
  • 使用背景工作進程或雲端函式處理儲存的資料。

例如,資料可能會加入 佇列至 Azure 佇列儲存體 ,或儲存在 Azure Blob 儲存體中。

如需詳細資訊,請參閱將要求本文系結為 StreamPipeReader

新的 Results.Stream 多載

我們引進了新的 Results.Stream 多載,以容納需要存取基礎 HTTP 回應資料流程而不需緩衝處理的案例。 這些多載也會改善 API 將資料串流至 HTTP 回應資料流程的情況,例如從 Azure Blob 儲存體。 下列範例會使用 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);
}

如需詳細資訊,請參閱 串流範例

最小 API 的具型別結果

在 .NET 6 中 IResult ,已引進 介面來表示從基本 API 傳回的值,這些 API 不會利用 ON 將傳回的物件序列化為 HTTP 回應的隱含支援 JS 。 靜態 Results 類別可用來建立代表不同回應類型的不同 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 公開使用。 使用具名方法而非 Lambda 時,實 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 介面

最小 API 的 OpenAPI 改善

Microsoft.AspNetCore.OpenApi NuGet 套件

Microsoft.AspNetCore.OpenApi 套件允許與端點的 OpenAPI 規格互動。 封裝可作為 OpenAPI 模型之間的連結,這些模型定義于套件中 Microsoft.AspNetCore.OpenApi ,以及基本 API 中所定義的端點。 封裝會提供 API 來檢查端點的參數、回應和中繼資料,以建構用來描述端點的 OpenAPI 注釋類型。

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 規格產生的描述和摘要。 您可以呼叫擴充方法 WithDescription ,或使用 WithSummary屬性 [EndpointDescription][EndpointSummary]) 。

如需詳細資訊,請參閱 基本 API 應用程式中的 OpenAPI

使用 IFormFile 和 IFormFileCollection 的檔案上傳

最低 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] 引數清單

最小 API 和 API 控制器

新問題詳細資料服務

問題詳細資料服務會實作 IProblemDetailsService 介面,其支援 建立 HTTP API 的問題詳細資料

如需詳細資訊,請參閱 問題詳細資料服務

路由群組

擴充 MapGroup 方法可協助組織具有通用前置詞的端點群組。 它可減少重複的程式碼,並允許使用單一呼叫方法來自訂整個端點群組,例如 RequireAuthorizationWithMetadata 新增 端點中繼資料的方法。

例如,下列程式碼會建立兩個類似的端點群組:

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;
}

在此案例中,您可以在結果中使用 201 Created 標頭的 Location 相對位址:

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 和 的要求,而且不需要任何驗證即可存取。 第二組端點只會比對前面加上 /private/todos 且需要驗證的要求。

端點 QueryPrivateTodos篩選處理站是一個本機函式,可修改路由處理常式的參數 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);
});

在上述範例中,即使已新增第二個,外部篩選也會在內部篩選之前記錄傳入要求。 由於篩選已套用至不同的群組,因此彼此相對新增的順序並不重要。 如果套用至相同的群組或特定端點,則會新增訂單篩選準則。

的要求 /outer/inner/ 會記錄下列專案:

/outer group filter
/inner group filter
MapGet filter

gRPC

JSON 轉碼

gRPC JS ON 轉碼是 ASP.NET Core延伸模組,可建立 REST gRPC 服務的具功能 JS ON API。 gRPC JS ON 轉碼允許:

  • 使用熟悉 HTTP 概念呼叫 gRPC 服務的應用程式。
  • ASP.NET Core gRPC 應用程式,以支援 gRPC 和 REST ful JS ON API,而不需複寫功能。
  • 藉由與Swashbuckle整合,從已 REST 轉碼的 API 產生 OpenAPI 的實驗性支援。

如需詳細資訊,請參閱ASP.NET Core gRPC 應用程式中的 gRPC JS ON 轉碼和使用OpenAPI 搭配 gRPC JS ON 轉碼 ASP.NET Core應用程式

ASP.NET Core 中的 gRPC 健康情況檢查

gRPC 健康情況檢查通訊協定是報告 gRPC 伺服器應用程式健康情況的標準。 應用程式會將健康情況檢查公開為 gRPC 服務。 它們通常會與外部監視服務搭配使用,以檢查應用程式的狀態。

gRPC ASP.NET Core已針對套件的 gRPC 健康情況檢查 Grpc.AspNetCore.HealthChecks 新增內建支援。 來自 .NET 健康狀態檢查的結果會回報給呼叫端。

如需詳細資訊,請參閱ASP.NET Core 中的 gRPC 健康情況檢查

改善通話認證支援

呼叫認證是設定 gRPC 用戶端以將驗證權杖傳送至伺服器的建議方式。 gRPC 用戶端支援兩項新功能,讓通話認證更容易使用:

  • 支援使用純文字連線的呼叫認證。 先前,如果連線受到 TLS 保護,gRPC 呼叫只會傳送呼叫認證。 在 上 GrpcChannelOptions 稱為 UnsafeUseInsecureChannelCallCredentials 的新設定,允許自訂此行為。 使用 TLS 保護連線的安全性含意。
  • gRPC 用戶端處理站可使用名為 AddCallCredentials 的新方法。 AddCallCredentials 是設定 gRPC 用戶端呼叫認證的快速方式,並與相依性插入 (DI) 整合良好。

下列程式碼會設定 gRPC 用戶端處理站以傳送 Authorization 中繼資料:

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 有兩個新的專案範本,可從空白的平板開始。 新的Blazor Server 應用程式空白Blazor WebAssembly 應用程式空白專案範本就像其非空白專案範本,但沒有範例程式碼。 這些空白範本只包含基本首頁,我們已移除 Bootstrap,讓您可以從不同的 CSS 架構開始。

如需詳細資訊,請參閱下列文章:

Blazor 自訂元素

套件 Microsoft.AspNetCore.Components.CustomElements 可讓您使用 Blazor 建置以標準為基礎的自訂 DOM 元素

如需詳細資訊,請參閱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 -returning 或 Task -returning 方法傳遞至 /@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:
    • 新增類型。
    • 新增巢狀類別。
    • 將靜態和實例方法新增至現有的類型。
    • 將靜態欄位和方法新增至現有的類型。
    • 將靜態 Lambda 新增至現有的方法。
    • 將擷取 this 的 Lambda 新增至先前擷 this 取的現有方法。

使用 MSAL 的動態驗證要求 Blazor WebAssembly

.NET 7 的新功能支援 Blazor WebAssembly 使用自訂參數在執行時間建立動態驗證要求,以處理進階驗證案例。

如需詳細資訊,請參閱下列文章:

Blazor WebAssembly 偵錯改善

Blazor WebAssembly 偵錯具有下列改善:

  • 支援 Just My Code 設定,以顯示或隱藏不在使用者程式碼中的類型成員。
  • 支援檢查多維度陣列。
  • 呼叫 Stack 現在會顯示非同步方法的正確名稱。
  • 改善的運算式評估。
  • 正確處理 new 衍生成員上的 關鍵字。
  • 支援 中的 System.Diagnostics 偵錯工具相關屬性。

System.Security.Cryptography WebAssembly 上的支援

.NET 6 支援在 WebAssembly 上執行時的 SHA 系列雜湊演算法。 .NET 7 藉由盡可能利用 SubtleCrypto 來啟用更多密碼編譯演算法,並在無法使用時 SubtleCrypto 回復至 .NET 實作。 .NET 7 中的 WebAssembly 支援下列演算法:

  • SHA1
  • SHA256
  • SHA384
  • SHA512
  • HMACSHA1
  • HMACSHA256
  • HMACSHA384
  • HMACSHA512
  • AES-CBC
  • PBKDF2
  • ][][!]

如需詳細資訊,請參閱 以 browser-wasm 為目標的開發人員可以使用 web Crypto API (dotnet/runtime #40074)

將服務插入自訂驗證屬性

您現在可以將服務插入自訂驗證屬性。 Blazor 設定 ValidationContext ,以便做為服務提供者使用。

如需詳細資訊,請參閱ASP.NET Core Blazor 表單和輸入元件

Input* 外部的元件 EditContext/EditForm

內建的輸入元件現在支援在元件標記中的 Razor 表單外部。

如需詳細資訊,請參閱ASP.NET Core Blazor 表單和輸入元件

專案範本變更

當去年發行 .NET 6 時,頁面的 HTML 標籤 _Host () 分割 _Host 在頁面與 .NET 6 Blazor Server 專案範本中的新 _Layout 頁面 (Pages/_Layout.chstmlPages/_Host.chstml) 。

在 .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 更新

MovementXMovementY 已新增至 MouseEventArgs

如需詳細資訊,請參閱ASP.NET Core Blazor 事件處理

新增 Blazor 載入頁面

專案 Blazor WebAssembly 範本有新的載入 UI,顯示載入應用程式的進度。

如需詳細資訊,請參閱ASP.NET Core Blazor 啟動

已改善 中驗證的診斷 Blazor WebAssembly

為了協助診斷應用程式中的 Blazor WebAssembly 驗證問題,可以使用詳細的記錄。

如需詳細資訊,請參閱ASP.NET Core Blazor 記錄

WebAssembly 上的 JavaScript Interop

JavaScript [JSImport]/[JSExport] Interop API 是新的低階機制,可在 和 JavaScript 型應用程式中使用 .NET Blazor WebAssembly 。 透過這個新的 JavaScript Interop 功能,您可以使用 .NET WebAssembly 執行時間從 JavaScript 叫用 .NET 程式碼,並從 .NET 呼叫 JavaScript 功能,而不需要對 UI 元件模型有任何相依性 Blazor 。

其他資訊:

驗證狀態提供者的條件式註冊

在 .NET 7 版本之前, AuthenticationStateProvider 已在服務容器 AddScoped 中向 註冊。 這很難偵錯應用程式,因為它在提供自訂實作時強制特定服務註冊順序。 由於內部架構隨著時間而變更,因此不再需要向 AddScoped 註冊 AuthenticationStateProvider

在開發人員程式碼中,對驗證狀態提供者服務註冊進行下列變更:

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

在上述範例中, ExternalAuthStateProvider 是開發人員的服務實作。

.NET WebAssembly 建置工具的改善

.NET 7 工作負載 wasm-tools 中的新功能,可協助改善效能並處理例外狀況:

如需詳細資訊,請參閱ASP.NET Core Blazor 的工具

Blazor Hybrid

外部 URL

已新增選項,允許在瀏覽器中開啟外部網頁。

如需詳細資訊,請參閱ASP.NET Core Blazor Hybrid 路由和導覽

安全性

新的指引適用于 Blazor Hybrid 安全性案例。 如需詳細資訊,請參閱下列文章:

效能

輸出快取中介軟體

輸出快取是新的中介軟體,可儲存來自 Web 應用程式的回應,並從快取提供回應,而不是每次計算它們。 輸出快取與回應快 不同,方式如下:

  • 快取行為可在伺服器上設定。
  • 快取專案可以程式設計方式失效。
  • 資源鎖定可降低 快取戳記擷取她的風險
  • 快取重新驗證表示伺服器可以傳回 304 Not Modified HTTP 狀態碼,而不是快取的回應本文。
  • 快取儲存媒體是可延伸的。

如需詳細資訊,請參閱 快取 概觀和 輸出快取中介軟體

HTTP/3 改善

此版本:

  • ASP.NET Core完全支援 HTTP/3,不再實驗性。
  • Kestrel改善 HTTP/3 的支援。 改善的兩個主要領域是與 HTTP/1.1 和 HTTP/2 的功能同位,以及效能。
  • 提供 HTTP/3 的完整支援 UseHttps(ListenOptions, X509Certificate2) 。 Kestrel 提供設定連線憑證的進階選項,例如連結至 伺服器名稱指示 (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);
            },
        });
    });
});

在 .NET 7 中完成大量工作,以減少 HTTP/3 配置。 您可以在下列 GitHub PR 中看到其中一些改善:

HTTP/2 效能改善

.NET 7 引進了處理 HTTP/2 要求方式 Kestrel 的重大重新架構。 ASP.NET Core具有忙碌 HTTP/2 連線的應用程式,將會降低 CPU 使用量和更高的輸送量。

先前,HTTP/2 多工處理實作依賴 鎖定 來控制哪些要求可以寫入基礎 TCP 連線。 安全線程佇列會取代寫入鎖定。 現在,要求現在會排入佇列,並讓專用取用者處理它們,而不是對抗哪些執行緒可以使用寫入鎖定。 先前浪費的 CPU 資源可供應用程式的其餘部分使用。

其中一個可以注意到這些改進的地方是在 gRPC 中,這是使用 HTTP/2 的熱門 RPC 架構。 Kestrel + gRPC 基準測試顯示大幅改善:

gRPC 伺服器串流效能

在 HTTP/2 框架撰寫程式碼中所做的變更,可在嘗試在單一 HTTP/2 連線上寫入資料的多個資料流程時改善效能。 我們現在會將 TLS 工作分派給執行緒集區,並更快速地釋放其他資料流程可取得的寫入鎖定來寫入資料。 在發生此寫入鎖定競爭的情況下,減少等候時間可能會大幅改善效能。 具有 TLS) 單一 (連線上 70 個數據流的 gRPC 基準測試,顯示每秒要求 (RPS) 這項變更的 ~15% 改善。

Http/2 WebSockets 支援

.NET 7 引進透過 HTTP/2 支援的 Kestrel Websockets、 SignalR JavaScript 用戶端,以及 SignalR 搭配 Blazor WebAssembly 。

透過 HTTP/2 使用 WebSockets 會利用新功能,例如:

  • 標頭壓縮。
  • 多工處理,可減少對伺服器提出多個要求時所需的時間和資源。

所有啟用 HTTP/2 的平臺都提供 Kestrel 這些支援的功能。 版本交涉會在瀏覽器和 Kestrel 中自動進行,因此不需要新的 API。

如需詳細資訊,請參閱 Http/2 WebSockets 支援

Kestrel 高核心機器的效能改善

Kestrel 用於 ConcurrentQueue<T> 許多用途。 其中一個用途是排程預設通訊端傳輸中的 Kestrel I/O 作業。 ConcurrentQueue根據相關聯的通訊端分割 可減少爭用,並增加具有許多 CPU 核心之機器的輸送量。

.NET 6 上高核心機器上的程式碼剖析在其中一個 Kestrel 其他 ConcurrentQueue 實例中顯示重大競爭, PinnedMemoryPool 其 Kestrel 用來快取位元組緩衝區。

在 .NET 7 中, Kestrel 記憶體集區的分割方式與其 I/O 佇列相同,這會導致高核心電腦上的爭用和更高的輸送量降低。 在 80 核心 ARM64 VM 上,我們在 TechEmpower 純文字基準測試中看到每秒回應的 500% 改善 (RPS) 。 在我們的 HTTPS JS ON 基準測試中,48 核心 AMD VM 的改善幾乎是 100%。

ServerReady 測量啟動時間的事件

使用 EventSource 的應用程式可以測量啟動時間,以瞭解並優化啟動效能。 中的 Microsoft.AspNetCore.HostingServerReady 事件代表伺服器準備好回應要求的點。

伺服器

用於測量啟動時間的新 ServerReady 事件

ServerReady已新增事件以測量 ASP.NET Core應用程式的啟動時間

IIS

IIS 中的陰影複製

陰影複製應用程式元件至適用于 IIS 的ASP.NET Core 模組 (ANCM) ,可提供比部署應用程式離線檔案來停止應用程式更好的使用者體驗。

如需詳細資訊,請參閱 IIS 中的陰影複製

其他

Kestrel 完整憑證鏈結改善

HttpsConnectionAdapterOptions具有X509Certificate2Collection類型的新ServerCertificateChain屬性,可讓您更輕鬆地驗證憑證鏈結,方法是允許指定包含中繼憑證的完整鏈結。 如需詳細資訊,請參閱 dotnet/aspnetcore#21513

dotnet watch

改善 dotnet watch 的主控台輸出

已改善 dotnet watch 的主控台輸出,以更符合 ASP.NET Core記錄,並使用 emoji 😍 來脫穎而出 😮 。

以下是新輸出的外觀範例:

dotnet watch 的輸出

如需詳細資訊,請參閱 此 GitHub 提取要求

將 dotnet watch 設定為一律重新開機以進行不快的編輯

Rude 編輯是無法熱重載的編輯。 若要將 dotnet watch 設定為一律重新開機,而不提示不進行不小心編輯,請將 DOTNET_WATCH_RESTART_ON_RUDE_EDIT 環境變數設定為 true

開發人員例外狀況頁面深色模式

深色模式支援已新增至開發人員例外狀況頁面,感謝 Patrick Westceptf的貢獻。 若要在瀏覽器中測試深色模式,請從開發人員工具頁面將模式設定為深色。 例如,在 Firefox 中:

F12 工具 FF 深色模式

在 Chrome 中:

F12 工具 Chrome 深色模式

使用 Program.Main 方法而非最上層語句的專案範本選項

.NET 7 範本包含一個選項,以不使用 最上層語句 ,並產生 namespaceMain 在類別上 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 管理 JS 開發中的 ON Web 權杖

新的 dotnet user-jwts 命令列工具可以建立和管理特定本機JS ON Web 權杖的應用程式, (JWT) 。 如需詳細資訊,請參閱 使用 dotnet user-jwts 管理 JS 開發中的 ON Web 權杖

支援 W3CLogger 中的其他要求標頭

您現在可以在 上使用 W3C 記錄器時,藉由呼叫 AdditionalRequestHeaders()W3CLoggerOptions 來指定要記錄的其他要求標頭:

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

如需詳細資訊,請參閱 W3CLogger 選項

要求解壓縮

新的 要求解壓縮中介軟體

  • 可讓 API 端點接受具有壓縮內容的要求。
  • Content-Encoding使用 HTTP 標頭自動識別並解壓縮包含壓縮內容的要求。
  • 不需要撰寫程式碼來處理壓縮的要求。

如需詳細資訊,請參閱 要求解壓縮中介軟體