ASP.NET Core 9.0 的新增功能

本文重点介绍 ASP.NET Core 9.0 中最重要的更改,并提供相关文档的链接。

本文已针对 .NET 9 预览版 3 进行了更新。

Blazor

本部分介绍 Blazor 的新功能。

构造函数注入

Razor 组件支持构造函数注入。

在以下示例中,部分(代码隐藏)类使用主构造函数注入了 NavigationManager 服务:

public partial class ConstructorInjection(NavigationManager navigation)
{
    protected NavigationManager Navigation { get; } = navigation;
}

有关详细信息,请参阅 ASP.NET Core Blazor 依赖项注入

交互式服务器组件的 Websocket 压缩

默认情况下,交互式服务器组件会为 WebSocket 连接 启用压缩,并将frame-ancestors内容安全策略 (CSP) 指令设置为 'self',这会仅允许在启用压缩时或提供 WebSocket 上下文的配置时将应用嵌入为该应用提供服务的来源的 <iframe> 中。

可以通过将 ConfigureWebSocketOptions 设为 null 来禁用压缩,这可以减少应用受攻击的风险,但可能会导致性能降低:

.AddInteractiveServerRenderMode(o => o.ConfigureWebSocketOptions = null)

请考虑使用带有值 'none'(需要单引号)的更严格的 frame-ancestors CSP,它允许 WebSocket 压缩,但会阻止浏览器将应用嵌入任何 <iframe>

.AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = "'none'")

有关更多信息,请参见以下资源:

处理 Blazor 中的键盘组合事件

新的 KeyboardEventArgs.IsComposing 属性指示键盘事件是否是组合会话的一部分。 跟踪键盘事件的组合状态对于处理国际字符输入法至关重要。

SignalR

本部分介绍 SignalR 的新功能。

SignalR 中心支持多态类型

中心方法现在可接受基类(而不是派生类)来实现多态方案。 需要注释基类型才能实现多形性

public class MyHub : Hub
{
    public void Method(JsonPerson person)
    {
        if (person is JsonPersonExtended)
        {
        }
        else if (person is JsonPersonExtended2)
        {
        }
        else
        {
        }
    }
}

[JsonPolymorphic]
[JsonDerivedType(typeof(JsonPersonExtended), nameof(JsonPersonExtended))]
[JsonDerivedType(typeof(JsonPersonExtended2), nameof(JsonPersonExtended2))]
private class JsonPerson
{
    public string Name { get; set; }
    public Person Child { get; set; }
    public Person Parent { get; set; }
}

private class JsonPersonExtended : JsonPerson
{
    public int Age { get; set; }
}

private class JsonPersonExtended2 : JsonPerson
{
    public string Location { get; set; }
}

最小 API

本部分介绍最小 API 的新功能。

TypedResults 添加了 InternalServerErrorInternalServerError<TValue>

TypedResults 类是一种有用的工具,用于从最小的 API 返回基于强类型的 HTTP 状态代码响应。 TypedResults 现在包括用于从终结点返回“500 内部服务器错误”响应的工厂方法和类型。 下面是返回 500 响应的示例:

var app = WebApplication.Create();

app.MapGet("/", () => TypedResults.InternalServerError("Something went wrong!"));

app.Run();

身份验证和授权

本部分介绍身份验证和授权的新功能。

OIDC 和 OAuth 参数自定义

OAuth 和 OIDC 身份验证处理程序现在具有 AdditionalAuthorizationParameters 选项,以便更轻松地自定义通常作为重定向查询字符串的一部分的授权消息参数。 在 .NET 8 及更早版本中,这需要在自定义处理程序中使用自定义 OnRedirectToIdentityProvider 回调或重写 BuildChallengeUrl 方法。 下面是 .NET 8 代码的示例:

builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
    options.Events.OnRedirectToIdentityProvider = context =>
    {
        context.ProtocolMessage.SetParameter("prompt", "login");
        context.ProtocolMessage.SetParameter("audience", "https://api.example.com");
        return Task.CompletedTask;
    };
});

前面的示例现在可以简化为以下代码:

builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
    options.AdditionalAuthorizationParameters.Add("prompt", "login");
    options.AdditionalAuthorizationParameters.Add("audience", "https://api.example.com");
});

配置 HTTP.sys 扩展身份验证标志

现在,可以使用 HTTP.sys AuthenticationManager 上的新 EnableKerberosCredentialCachingCaptureCredentials 属性来配置 HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHINGHTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL HTTP.sys 标志,以优化 Windows 身份验证的处理方式。 例如:

webBuilder.UseHttpSys(options =>
{
    options.Authentication.Schemes = AuthenticationSchemes.Negotiate;
    options.Authentication.EnableKerberosCredentialCaching = true;
    options.Authentication.CaptureCredentials = true;
});

杂项

以下部分介绍了其他新功能。

开发者异常页上的终结点元数据

添加到 MVC 操作、最小 API 和 gRPC 方法的属性是终结点元数据的示例。 ASP.NET Core 使用终结点元数据来控制终结点行为,例如路由、身份验证和授权、响应缓存、速率限制、OpenAPI 生成等。

.NET 9 将元数据添加到开发者异常页面。 新的元数据信息会与其他路由信息一起显示在 Routing 部分中。 利用此信息,可以更轻松地在开发过程中调试 ASP.NET Core 错误。 下图显示了开发者异常页上的新元数据信息:

开发者异常页上的新元数据信息

字典调试改进

字典和其他键值集合的调试显示具有改进的布局。 键显示在调试程序的键列中,而不是与值连接在一起。 下图显示了调试程序中字典的旧显示和新显示。

之前:

以前的调试器体验

之后:

新的调试器体验

ASP.NET Core 有许多键值集合。 这种改进的调试体验适用于:

  • HTTP 头
  • 查询字符串
  • 窗体
  • Cookies
  • 查看数据
  • 路由数据
  • 功能