ASP.NET Core updates in. NET 7 RC1

ASP.NET Core updates in. NET 7 RC1

NET 7 Release Candidate 1 (RC1) is now available and includes many major new improvements to ASP.NET Core.

最后更新 9/15/2022 9:23 AM
Daniel Roth
预计阅读 18 分钟
分类
.NET
标签
.NET C# ASP.NET Core

原文链接:https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-rc-1/

Author: Daniel Roth

The Wolf at the End of the Desert

.NET 7 Release Candidate 1 (RC1) 现已推出,其中包括对 ASP.NET Core 的许多重大新改进。

Here is a summary of the new features in this preview:

  • Dynamic authentication requests in Blazor WebAssembly
  • Handle location change events
  • Blazor WebAssembly debugging improvements
  • NET WebAssembly project building tool for. NET 6 projects
  • NET JavaScript Interoperability on WebAssembly
  • Kestrel's complete certificate chain improvements
  • Faster HTTP/2 uploads
  • HTTP/3 improvements
  • Experimental Kestrel support for WebTransport via HTTP/3
  • Experimental OpenAPI support for gRPC JSON transcoding
  • rate-limiting middleware improvements
  • macOS Development Certificate Improvements

有关为 .NET 7 计划的 ASP.NET Core 工作的更多详细信息,请参阅 GitHub 上的 .NET 7 的完整 ASP.NET Core 路线图

start using

要开始使用 .NET 7 Release Candidate 1 中的 ASP.NET Core,请安装 .NET 7 SDK

如果你在 Windows 上使用 Visual Studio,我们建议安装最新的Visual Studio 2022 预览版。如果您使用的是 macOS,我们建议您安装最新的Visual Studio 2022 for Mac 预览版

To install the latest. NET WebAssembly build tool, run the following command from an elevated command prompt:

dotnet workload install wasm-tools

Upgrade existing projects

To upgrade an existing ASP.NET Core application from. NET 7 Preview 7 to. NET 7 RC1:

  • 将所有 Microsoft.AspNetCore._ 包引用更新为.7.0.0-rc.1._
  • 将所有 Microsoft.Extensions._ 包引用更新为.7.0.0-rc.1._

另请参阅.NET 7 的 ASP.NET Core 中的重大更改的完整列表。

Dynamic authentication requests in Blazor WebAssembly

Blazor 为使用 OpenID Connect 和各种身份提供程序(包括 Azure Active Directory (Azure AD) 和 Azure AD B2C)的身份验证提供开箱即用的支持。在 .NET 7 中,Blazor 现在支持在运行时使用自定义参数创建动态身份验证请求,以处理 Blazor WebAssembly 应用中更高级的身份验证方案。要指定其他参数,请使用新的InteractiveRequestOptions类型和NavigateToLogin``辅助方法NavigationManager

For example, you can specify a login prompt for your identity provider to authenticate like this:

InteractiveRequestOptions requestOptions = new()
{
    Interaction = InteractionType.SignIn,
    ReturnUrl = NavigationManager.Uri,
};
requestOptions.TryAddAdditionalParameter("login_hint", "user@example.com");
NavigationManager.NavigateToLogin("authentication/login", requestOptions);

同样,您可以指定 OpenID Connect prompt 参数,例如当您想要强制交互式登录时:

InteractiveRequestOptions requestOptions = new()
{
    Interaction = InteractionType.SignIn,
    ReturnUrl = NavigationManager.Uri,
};
requestOptions.TryAddAdditionalParameter("prompt", "login");
NavigationManager.NavigateToLogin("authentication/login", requestOptions);

您可以使用IAccessTokenProvider直接用于请求令牌时指定这些选项:

var accessTokenResult = await AccessTokenProvider.RequestAccessToken(
    new AccessTokenRequestOptions
    {
        Scopes = new[] { "SecondAPI" }
    });

if (!accessTokenResult.TryGetToken(out var token))
{
    accessTokenResult.InteractiveOptions.AddAdditionalParameter("login_hint", "user@example.com");
    NavigationManager.NavigateToLogin(accessTokenResult.InteractiveRequestUrl, accessTokenResult.InteractionOptions);
}

当无法获取令牌时,您还可以通过AuthorizationMessageHandler指定身份验证请求选项:

try
{
    await httpclient.Get("/orders");

}
catch (AccessTokenNotAvailableException ex)
{
    ex.Redirect(requestOptions =>
    {
        requestOptions.AddAdditionalParameter("login_hint", "user@example.com");
    });
}

Any other parameters specified for the authentication request are passed to the underlying authentication library and then processed by it.

Note: Specifying additional parameters for msal.js is not fully implemented, but is expected to be completed in an upcoming release.

Handle location change events

Blazor in. NET 7 now supports handling location change events. This allows you to warn users of unsaved work or perform related actions when they perform page navigation.

使用NavigationManager服务的RegisterLocationChangingHandler方法注册处理程序用于处理位置更改事件。然后,您的处理程序可以在导航时执行异步工作,或者通过调用LocationChangingContextPreventNavigation取消导航。RegisterLocationChangingHandler返回一个IDisposable实例,该实例在释放时会删除相应的位置更改处理程序。

For example, the following handler prevents navigation to the counter page:

var registration = NavigationManager.RegisterLocationChangingHandler(async context =>
{
    if (context.TargetLocation.EndsWith("counter"))
    {
        context.PreventNavigation();
    }
});

请注意,您的处理程序只会被用于应用程序内的内部导航调用。外部导航只能使用 JavaScript 中的beforeunload 事件同步处理。

NavigationLock组件使处理位置变化事件的常见场景更容易。NavigationLock公开一个OnBeforeInternalNavigation回调,您可以使用它来拦截和处理内部位置更改事件。如果您希望用户也确认外部导航,您可以使用该ConfirmExternalNavigations属性,它将拦截beforeunload事件并触发浏览器特定提示。

<EditForm EditContext="editContext" OnValidSubmit="Submit">
    ...
</EditForm>
<NavigationLock OnBeforeInternalNavigation="ConfirmNavigation" ConfirmExternalNavigation />

@code {
    private readonly EditContext editContext;

    ...

    // Called only for internal navigations
    // External navigations will trigger a browser specific prompt
    async Task ConfirmNavigation(LocationChangingContext context)
    {
        if (editContext.IsModified())
        {
            var isConfirmed = await JS.InvokeAsync<bool>("window.confirm", "Are you sure you want to leave this page?");

            if (!isConfirmed)
            {
                context.PreventNavigation();
            }
        }
    }
}

Blazor WebAssembly debugging improvements

Blazor WebAssembly debugging in. NET 7 now has the following improvements:

  • Support Just My Code settings to show or hide type members that are not in user code
  • Support checking multidimensional arrays
  • The call stack now displays the correct name for the asynchronous method
  • Improved expression evaluation
  • 正确处理派生成员的new关键字
  • System.Diagnostics中支持调试器相关的属性

Build tool for. NET WebAssembly for. NET 6 projects

现在,在使用 .NET 7 SDK 时,您可以将 .NET WebAssembly 构建工具用于 .NET 6 项目。新的wasm-tools-net6工作负载包括用于 .NET 6 项目的 .NET WebAssembly 构建工具,以便它们可以与 .NET 7 SDK 一起使用。要安装新wasm-tools-net6工作负载,请从提升的命令提示符运行以下命令:

dotnet workload install wasm-tools-net6

安装 .NET WebAssembly 构建工具带来的wasm-tools工作负载是为 .NET 7 项目准备的(翻译有点拗口,这句可能翻译错了,原文是:The existing wasm-tools workload installs the .NET WebAssembly build tools for .NET 7 projects.)。但是,.NET 7 版本的 .NET WebAssembly 构建工具与使用 .NET 6 构建的现有项目不兼容。需要同时支持 .NET 6 和 .NET 7 使用 .NET WebAssembly 构建工具的项目将需要使用 multi-targeting。

NET JavaScript Interoperability on WebAssembly

NET 7 introduces a new low-level mechanism for using. NET in JavaScript based applications. With this new JavaScript interoperability feature, you can use the. NET WebAssembly runtime to call. NET code from JavaScript and JavaScript features from. NET without relying on the Blazor UI component model.

查看新的 JavaScript 互操作功能的最简单方法是在wasm-experimental工作负载中使用新的实验模板:

dotnet workload install wasm-experimental

This workload contains two project templates: the WebAssembly Browser App and the WebAssembly Console App. These templates are experimental, which means that their developer workflow has not yet been fully organized (for example, these templates are not yet running in Visual Studio). But. NET 7 supports the. NET and JavaScript APIs used in these templates and provides the foundation for using. NET on WebAssembly via JavaScript.

You can create a WebAssembly browser application by running the following command:

dotnet new wasmbrowser

This template creates a simple Web application that demonstrates how to use both. NET and JavaScript in a browser. The WebAssembly console application is similar, but runs as a Node.js console application rather than a browser-based Web application.

创建的示例项目中的 main.js 中的 JavaScript 模块演示了如何从 JavaScript 运行 .NET 代码。相关 API 是从 dotnet.js 导入的。这些 API 使您能够设置可以导入到 C# 代码中的命名模块,以及调用 .NET 代码公开的方法,包括Program.Main

import { dotnet } from "./dotnet.js";

const is_browser = typeof window != "undefined";
if (!is_browser) throw new Error(`Expected to be running in a browser`);

// Setup the .NET WebAssembly runtime
const { setModuleImports, getAssemblyExports, getConfig, runMainAndExit } =
  await dotnet
    .withDiagnosticTracing(false)
    .withApplicationArgumentsFromQuery()
    .create();

// Set module imports that can be called from .NET
setModuleImports("main.js", {
  window: {
    location: {
      href: () => globalThis.window.location.href,
    },
  },
});

const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting(); // Call into .NET from JavaScript
console.log(text);

document.getElementById("out").innerHTML = `${text}`;
await runMainAndExit(config.mainAssemblyName, ["dotnet", "is", "great!"]); // Run Program.Main

要导入 JavaScript 函数以便可以从 C# 调用它,请在匹配的方法签名上使用新的JSImportAttribute

[JSImport("window.location.href", "main.js")]
internal static partial string GetHRef();

JSImportAttribute的第一个参数是要导入的 JavaScript 函数的名称,第二个参数是模块的名称,这两个参数都是由 main.js 中的setModuleImports调用设置的。

在导入的方法签名中,您可以对参数和返回值使用 .NET 类型,这些类型将为您编组。使用JSMarshalAsAttribute<T>控制导入的方法参数的编组方式。例如,您可以选择将一个long 编组为JSType.NumberJSType.BigInt。您可以将Action/Func回调作为参数传递,这些参数将被编组为可调用的 JavaScript 函数。您可以同时传递 JavaScript 和托管对象引用,它们将被编组为代理对象,使对象在边界上保持活动状态,直到代理被垃圾回收。您还可以导入和导出带Task返回值的异步方法,它将作为 JavaScript promises 进行编组。在导入和导出的方法上,大多数封装类型作为参数和返回值双向工作,。

使用JSExportAttribute导出 .NET 方法以便可以从 JavaScript 调用:

[JSExport]
internal static string Greeting()
{
    var text = $"Hello, World! Greetings from {GetHRef()}";
    Console.WriteLine(text);
    return text;
}

Blazor 提供了自己的基于 IJSRuntime 接口的 JavaScript 互操作机制,该机制在所有 Blazor 托管模型中得到统一支持。这种常见的异步抽象使库作者能够构建可在 Blazor 生态系统中共享的 JavaScript 互操作库,并且仍然是在 Blazor 中执行 JavaScript 互操作的推荐方式。但是,在 Blazor WebAssembly 应用程序中,您还可以选择IJSInProcessRuntime进行同步 JavaScript 互操作调用,甚至使用IJSUnmarshalledRuntime进行解组调用。 IJSUnmarshalledRuntime使用起来很棘手,仅部分支持。在 .NET 7 中IJSUnmarshalledRuntime现在已经过时,应该用[JSImport]/[JSExport]机制替换。Blazor 不直接公开从 JavaScript 使用的dotnet运行时实例,但仍然可以通过.getDotnetRuntime(0)调用。您还可以通过在 C#代码中调用JSHost.ImportAsync导入 JavaScript 模块,这可以使模块导出对 [JSImport]可见。

Kestrel's complete certificate chain improvements

类型X509Certificate2CollectionHttpsConnectionAdapterOptions具有新属性ServerCertificateChaintype ,通过允许指定包含中间证书的完整链,可以更轻松地验证证书链。有关详细信息,请参阅dotnet/aspnetcore#21513

Faster HTTP/2 uploads

We have increased Kestrel's default HTTP/2 upload connection window size from 128KB to 1MB, which significantly increases HTTP/2 upload speeds for high-latency connections using Kestrel's default configuration.

After introducing an artificial delay of only 10 milliseconds, we tested the impact of increasing this limit by using a single stream to upload a 108 MB file upload on localhost and saw an approximately 6-fold increase in upload speeds.

The following screenshot compares the time it takes to upload 108 MB in Edge's Development Tools Network tab:

  • Previous: 26.9 seconds
  • After: 4.3 seconds

HTTP/3 improvements

NET 7 RC1 continues to improve Kestrel's support for HTTP/3. The two main areas of improvement are functional parity with HTTP/1.1 and HTTP/2 and performance.

此版本最大的特点是完全支持ListenOptions.UseHttps使用 HTTP/3。Kestrel 提供了用于配置连接证书的高级选项,例如拦截到Server Name Indication (SNI)

The following example shows how to use SNI callbacks to resolve TLS options:

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 = ResolveCertForHost(context.ClientHelloInfo.ServerName)
                };
                return new ValueTask<SslServerAuthenticationOptions>(options);
            },
        });
    });
});

We have also done a lot of work to reduce HTTP/3 allocations in. NET 7 RC1. You can see some of these improvements here:

Experimental Kestrel support for WebTransport via HTTP/3

我们很高兴地宣布在 Kestrel 中对基于 HTTP/3 的 WebTransport 的内置实验性支持。此功能是由我们优秀的实习生 Daniel 编写的!WebTransport 对于类似于 WebSockets 的传输协议是一个新的草案规范,它允许每个连接使用多个流。这对于拆分通信通道并因此避免线头阻塞很有用。例如,考虑一个基于网络的在线游戏,其中游戏状态在一个双向流上传输,玩家对游戏语音聊天功能的语音在另一个双向流上传输,而玩家的控制在单向流上传输。使用 WebSockets,这一切都需要放在单独的连接上或压缩到单个流中。使用 WebTransport,您可以将所有流量保留在一个连接上,但将它们分成自己的流,如果一个流阻塞,其他流将继续不间断。

Additional details will be provided in a separate blog post.

Experimental OpenAPI support for gRPC JSON transcoding

gRPC JSON 转码是 .NET 7 中的一项新功能,用于将 gRPC API 转换为 RESTful API。

NET 7 RC1 adds experimental support for generating OpenAPIs from the gRPC Transcoding RESTful API. The OpenAPI with gRPC JSON transcoding is a much-needed feature, and we are happy to provide a way to combine these great technologies. The NuGet package is experimental in. NET 7, giving us time to explore the best way to integrate these features.

To enable the OpenAPI using gRPC JSON transcoding:

  • 添加对Microsoft.AspNetCore.Grpc.Swagger的包引用。版本必须为 0.3.0-xxx 或更高版本。
  • 在启动时配置 Swashbuckle。该AddGrpcSwagger方法将 Swashbuckle 配置为包含 gRPC 端点。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc().AddJsonTranscoding();
builder.Services.AddGrpcSwagger();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1",
        new OpenApiInfo { Title = "gRPC transcoding", Version = "v1" });
});

var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
app.MapGrpcService<GreeterService>();

app.Run();

To confirm that Swashbuckle is generating Swagger for the RESTful gRPC service, launch the application and navigate to the Swagger UI page:

Improvement of current-limiting middleware

We have added many features to the current-limiting middleware in. NET 7 RC1 to make it more powerful and easier to use.

我们添加了可用于启用或禁用给定端点上的速率限制的属性。例如,以下是如何将命名策略应用MyControllerPolicy到控制器:

public class MyController : Controller
{
    [EnableRateLimitingAttribute("MyControllerPolicy")]
    public IActionResult Index()
    {
        return View();
    }
}

You can also disable rate limiting completely on a given endpoint or group of endpoints. Suppose you have rate limiting enabled on a set of endpoints:

app.MapGroup("/public/todos").RequireRateLimiting("MyGroupPolicy");

You can then disable rate limits for specific endpoints in the group, as follows:

app.MapGroup("/public/todos/donothing").DisableRateLimiting();

您现在还可以将策略直接应用于端点。与命名策略不同,以这种方式添加的策略不需要在RateLimiterOptions. 假设您已经定义了一个策略类型:

public class MyRateLimiterPolicy : IRateLimiterPolicy<string>
{
...
}

You can add an instance of it directly to the endpoint, as follows:

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

最后,我们更新了RateLimiterOptions便捷方法以采用Action<Options>而不是Options实例,还添加了IServiceCollection使用速率限制的扩展方法。因此,要在您的应用中启用上述所有速率限制策略,您可以执行以下操作:

builder.Services.AddRateLimiter(options =>
{
    options.AddTokenBucketLimiter("MyControllerPolicy", options =>
    {
        options.TokenLimit = 1;
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 1;
        options.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
        options.TokensPerPeriod = 1;
    })
    .AddPolicy<string>("MyGroupPolicy", new MyRateLimiterPolicy());
});

这会将 TokenBucketLimiter应用于您的控制器,将您的自定义MyRateLimiterPolicy应用于匹配端点./public/todos(除了/public/todos/donothing),并将您的自定义MyRateLimiterPolicy应用于/

macOS Development Certificate Improvements

In this release, we have made some significant quality improvements to the macOS user experience of developing certificates using HTTPS, greatly reducing the number of certificates that display authentication prompts when creating, trusting, reading, and deleting ASP.NET Core HTTPS development. This has been a pain point when ASP.NET Core developers on macOS try to use development certificates in their workflows.

在此版本中,通过dotnet dev-certs工具在 macOS 上生成的开发证书具有更窄的信任范围,现在将设置添加到每个用户的信任设置中而不是系统范围内,并且 Kestrel 将能够绑定到这些新证书而无需访问系统钥匙串。作为这项工作的一部分,还对质量进行了一些改进,例如重新处理一些面向用户的消息以提高清晰度和准确性。

When using HTTPS during development on macOS, these changes combine to lead to a smoother experience and fewer password prompts.

Check out how the new Blazor update works!

有关 Blazor WebAssembly 中的动态身份验证请求、Blazor WebAssembly 调试改进以及 WebAssembly 上的 .NET JavaScript 互操作的实时演示,请参阅我们最近的Blazor 社区站会

give feedback

我们希望您喜欢 .NET 7 中的 ASP.NET Core 预览版。通过在GitHub 上提交问题,让我们知道您对这些新改进的看法。

Thank you for trying ASP.NET Core!

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 6/20/2024

CodeWF.EventBus: Lightweight event bus for smoother communication

CodeWF.EventBus, a flexible event bus library that enables decoupling communication between modules. Supports multiple. NET project types, such as WPF, WinForms, ASP.NET Core, etc. Adopt concise design to easily implement command publishing and subscribing, request and response. Ensure that incidents are properly handled through orderly incident handling. Streamline your code and improve system maintainability.

继续阅读
同分类 / 同标签 1/19/2024

FluentValidation verification tutorial based on. NET

FluentValidation is a verification framework developed based on. NET. It is open source, free, and elegant. It supports chain operations. It is easy to understand and has complete functions. It can still be deeply integrated with MVC5, WebApi2 and ASP.NET CORE. It provides more than a dozen commonly used validators within the components. It is scalable, supports custom validators, and supports localized multiple languages.

继续阅读