我们都知道在 6 月 12 日的时候微软发布了. NET Core 3.0 的第 6 个预览版. 针对. NET Core 3.0 的发布我们国内的微软 MVP - 汪宇杰还发布的官翻版的博文进行了详细的介绍. 具体的可以关注 "汪宇杰博客" 公众号, 或者我的 "DotNetCore 实战" 公众号然后在历史文章里面进行查阅. 而我们这篇文章将会介绍本次更新中对 ASP.NET Core 和 Blazor 所做的更新. 当然本文的大部分内容翻译自 ASP.NET 的首席项目经理 Daniel Roth 的介绍.
注: 英语能力好的可以直接到文章末尾查看英文链接进行阅读.
本文链接: https://www.cnblogs.com/yilezhu/p/11031441.html
以下是此预览版中的新增功能列表:
新 Razor 特性:@attribute,@code,@key,@namespace,@functions 中的标记
Blazor 指令属性
Blazor 应用程序的身份验证和授权支持
Razor 类库中的静态资产
JSON.NET 不再在项目模板中引用
证书和 Kerberos 身份验证
SignalR 自动重新连接
托管 gRPC 客户端
gRPC 客户端工厂
gRPC 拦截器
有关其他详细信息和已知问题, 请参阅发行说明 https://aka.ms/netcore3releasenotes .
开始
要在. NET Core 3.0 Preview 6 中开始使用 ASP.NET Core, 请安装. NET Core 3.0 Preview 6 SDK https://aka.ms/netcore3download
如果您在 Windows 上使用 Visual Studio 进行的话, 则还需要安装 Visual Studio 2019 的最新预览 https://visualstudio.com/preview .
对于最新的客户端 Blazor 模板, 还可以从 Visual Studio Marketplace 安装最新的 Blazor 扩展 https://go.microsoft.com/fwlink/?linkid=870389 .
升级现有项目
要将现有的 ASP.NET Core 应用程序升级到. NET Core 3.0 Preview 6, 请按照 ASP.NET Core 文档中的迁移步骤进行操作.
另请参阅 ASP.NET Core 3.0 中的重大更改的完整列表.
要将现有的 ASP.NET Core 3.0 Preview 5 项目升级到 Preview 6:
更新 Microsoft.AspNetCore.* 包引用到 3.0.0-preview6.19307.2
在 Blazor 应用程序中:
重命名 @functions 为 @code
更新 Blazor 特定属性和事件处理程序以使用新的指令属性语法(参见下文)
删除任何关于
App.UseBlazor<TStartup>()
的调用, 换成在 App.UseRouting()调用之前调用
App.UseClientSideBlazorFiles<TStartup>()
的方式. 还要在 App.UseEndpoints()的调用中调用
- endpoints.MapFallbackToClientSideBlazor<TStartup>("index.html")
- .
之前的调用方式
- App.UseRouting();
- App.UseEndpoints(endpoints =>
- {
- endpoints.MapDefaultControllerRoute();
- });
- App.UseBlazor<Client.Startup>();
更新之后的调用方式
- App.UseClientSideBlazorFiles<Client.Startup>();
- App.UseRouting();
- App.UseEndpoints(endpoints =>
- {
- endpoints.MapDefaultControllerRoute();
- endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
- });
Razor 的新特性
我们 (因为是 ASP.NET 的首席项目经理 Daniel Roth 写的博客, 所以用第一人称) 在此版本中添加了对以下新 Razor 语言功能的支持.
@attribute
新的 @attribute 指令将指定的属性添加到生成的类中.
- @attribute [Authorize]
- @code
.razor 文件 (在. cshtml 文件中不支持) 中使用了新的 @code 指令来指定要作为附加成员添加到生成的类中的代码块. 它相当于 @functions, 但现在有了更好的名称.
- @code {
- int currentCount = 0;
- void IncrementCount()
- {
- currentCount++;
- }
- }
- @key
.razor 文件中使用了新的 @key 指令属性, 以指定 Blazor diffing 算法可用于保留列表中的元素或组件的值(任何对象或唯一标识符).
- <div>
- @foreach (var flight in Flights)
- {
- <DetailsCard @key="flight" Flight="@flight" />
- }
- </div>
要了解需要此功能的原因, 请想象一下不实用此功能来呈现包含航班详细信息的卡片列表的场景:
- <div>
- @foreach (var flight in Flights)
- {
- <DetailsCard Flight="@flight" />
- }
- </div>
如果将新航班添加到航班列表的中间, 则现有的详细信息卡实例应保持不受影响, 并且应在呈现的输出中插入一个新的详细信息卡.
要想象这个, 如果 Flights 以前包含[F0, F1, F2], 那么这是之前的状态:
- DetailsCard0,Flight = F0
- DetailsCard1,Flight = F1
- DetailsCard2,Flight = F2
...... 如果我们在索引 1 中插入一个新的项目 fnew, 这就是所期望的插入之后的状态:
- DetailsCard0,Flight = F0
- DetailsCardNew,Flight = FNew
- DetailsCard1,Flight = F1
- DetailsCard2,Flight = F2
但是, 实际插入后的状态如下:
- DetailsCard0,Flight = F0
- DetailsCard1,Flight = FNew
- DetailsCard2,Flight = F1
- DetailsCardNew,Flight = F2
系统无法知道 DetailsCard2 或 DetailsCard3 应保留它们与旧航班实例的关联, 因此它只会将它们与列表中与其位置匹配的航班重新关联. 因此, DetailsCard1 和 DetailsCard2 使用新数据完全重建自己, 这是浪费的, 有时甚至会导致用户可见问题(例如, 输入焦点意外丢失).
通过使用 @keydiffing 算法添加键可以关联新旧元素或组件.
@namespace
在 *_Imports.razor * 文件中使用时, 指定生成的类或名称空间前缀的名称空间. 该 @namespace 指令现在适用于页面和视图 (.cshtml) 应用程序, 但现在它也支持组件(.razor).
@namespace MyNamespace
标记 @functions 和本地功能
在视图和页面 (.cshtml 文件) 中, 您现在可以在 @functions 块和本地函数中的方法内添加标记.
- @{ GreetPerson(person); }
- @functions {
- void GreetPerson(Person person)
- {
- <p>Hello, <em>@person.Name!</em></p>
- }
- }
Blazor 指令属性
Blazor 使用各种属性来影响组件的编译方式(例如 ref,bind, 事件处理程序等). 随着时间的推移, 这些属性已经有机地添加到 Blazor 并使用不同的语法. 在这个 Blazor 版本中, 我们已经标准化了指令属性的通用语法. 这使得 Blazor 使用的 Razor 语法更加一致和可预测. 它还为未来的可扩展性铺平了道路.
指令属性都遵循以下语法, 其中括号中的值是可选的:
@directive(-suffix(:name))(="value")
一些有效的例子:
- <!-- directive -->
- <div @directive>
- ...
- </div>
- <div @directive="value">
- </div>
- <!-- directive with key/value arg-->
- <div @directive:key>
- ...
- </div>
- <div @directive:key="value">
- </div>
- <!-- directive with suffix -->
- <div @directive-suffix>
- </div>
- <div @directive-suffix="value">
- </div>
- <!-- directive with suffix and key/value arg-->
- <div @directive-suffix:key>
- </div>
- <div @directive-suffix:key="value">
- </div>
所有 Blazor 内置指令属性都已更新为使用此新语法, 如下所述.
事件处理程序
在 Blazor 中指定事件处理程序现在使用新的指令属性语法而不是普通的 HTML 语法. 语法类似于 HTML 语法, 但现在具有前导 @字符. 这使得 C#事件处理程序与 JS 事件处理程序不同.
<button @onclick="@Clicked">Click me!</button>
为 C#事件处理程序指定委托时,@属性值当前仍需要前缀, 但我们希望在将来的更新中删除此要求.
在将来, 我们还希望使用指令属性语法来支持事件处理程序的其他功能. 例如, 停止事件传播可能看起来像这样(尚未实现, 但它让您了解现在由指令属性启用的方案):
<button @onclick="Clicked" @onclick:stopPropagation>Click me!</button>
捆绑
- <input @bind="myValue">
- ...
- </input>
- <input @bind="myValue" @bind:format="mm/dd">
- ...
- </input>
- <MyButton @bind-Value="myValue">
- ...
- </MyButton>
键
<div @key="id">...</div>
参考
<button @ref="myButton">...</button>
Blazor 应用程序的身份验证和授权支持
Blazor 现在内置了对处理身份验证和授权的支持. 服务器端 Blazor 模板现在支持使用 ASP.NET Core Identity,Azure AD 和 Azure AD B2C 启用所有标准身份验证配置的选项. 我们还没有更新 Blazor webAssembly 模板以支持这些选项, 但我们计划在. NET Core 3.0 发布之后这样做.
要创建启用了身份验证的新 Blazor 应用程序:
创建一个新的 Blazor(服务器端)项目, 然后选择链接以更改身份验证配置. 例如, 选择 "个人用户帐户" 和 "在应用程序中存储用户帐户" 以将 Blazor 与 ASP.NET Core Identity 一起使用:
运行应用程序. 该应用程序包含顶行中的链接, 用于注册为新用户并登录.
选择 "注册" 链接以注册新用户.
选择 "应用迁移" 以将 ASP.NET Core Identity 迁移应用于数据库.
你现在应该登录了.
选择您的用户名以编辑您的用户个人资料.
在 Blazor 应用程序中, Startup 使用标准 ASP.NET Core 中间件在类中配置身份验证和授权.
- App.UseRouting();
- App.UseAuthentication();
- App.UseAuthorization();
- App.UseEndpoints(endpoints =>
- {
- endpoints.MapControllers();
- endpoints.MapBlazorHub();
- endpoints.MapFallbackToPage("/_Host");
- });
使用 ASP.NET Core Identity 时, 所有与身份相关的 UI 问题都由框架提供的默认身份 UI 处理.
- services.AddDefaultIdentity<IdentityUser>()
- .AddEntityFrameworkStores<ApplicationDbContext>();
应用程序顶行中的身份验证相关链接使用新的内置 AuthorizeView 组件呈现, 该组件根据身份验证状态显示不同的内容.
- LoginDisplay.razor
- <AuthorizeView>
- <Authorized>
- <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
- <a href="Identity/Account/LogOut">Log out</a>
- </Authorized>
- <NotAuthorized>
- <a href="Identity/Account/Register">Register</a>
- <a href="Identity/Account/Login">Log in</a>
- </NotAuthorized>
- </AuthorizeView>
该 AuthorizeView 组件仅在授权用户时显示其子内容. 可替代地, AuthorizeView 采用参数用于指定不同模板当用户是 Authorized,NotAuthorized, 或 Authorizing. 当前的身份验证状态通过隐式 context 参数传递给这些模板. 您还可以指定 AuthorizeView 用户必须满足的特定角色或授权策略才能查看授权视图.
要授权访问 Blazor 应用程序中的特定页面, 请使用普通的 [authorize] 属性. 可以使用新的 @attribute 指令将 [authorize] 属性应用于组件..
- @using Microsoft.AspNetCore.Authorization
- @attribute [Authorize]
- @page "/fetchdata"
要指定在未授权用户或仍处于授权处理时需要授权的页面上显示的内容, 请使用组件上的 NotAuthorizedContent 和 AuthorizingContent 参数 Router. 这些 Router 参数仅在此版本的客户端 Blazor 中提供支持, 但在将来的更新中将为服务器端 Blazor 启用它们.
AuthenticationStateProvider 无论是在服务器上运行还是在浏览器中运行客户端, 新服务都会以统一的方式使 Blazor 应用程序可以使用身份验证状态. 在服务器端 Blazor 应用程序中 AuthenticationStateProvider, 用户从 HttpContext 建立与服务器的连接的表面. 客户端 Blazor 应用程序可以根据应用程序配置自定义 AuthenticationStateProvider. 例如, 它可以通过查询服务器上的端点来检索当前用户信息.
Task<AuthenticationState > 使用该 CascadingAuthenticationState 组件将身份验证状态作为级联值提供给应用程序. 然后, AuthorizeView 和 Router 组件使用此级联值来授权对 UI 的特定部分的访问.
- App.razor
- <CascadingAuthenticationState>
- <Router AppAssembly="typeof(Startup).Assembly">
- <NotFoundContent>
- <p>Sorry, there's nothing at this address.</p>
- </NotFoundContent>
- </Router>
- </CascadingAuthenticationState>
Razor 类库中的静态资产
Razor 类库现在可以包含静态资源, 如 JavaScript,CSS 和图像. 然后, 可以通过引用 Razor 类库项目或通过包引用将这些静态资产包含在 ASP.NET Core 应用程序中.
要在 Razor 类库中包含静态资源, 请将一个 wwwroot 文件夹添加到 Razor 类库中, 并在该文件夹中包含所有必需的文件.
当具有静态资产的 Razor 类库被引用为项目引用或作为包时, 来自库的静态资源在路径前缀 *_content / {LIBRARY NAME} /* 下可供应用程序使用. 静态资源保留在其原始文件夹中, Razor 类库中静态资产内容的任何更改都会反映在应用程序中而不进行重建.
发布应用程序后, 所有引用的 Razor 类库中的伴随资源将以相同的前缀复制到已发布应用程序的 wwwroot 文件夹中.
要尝试使用 Razor 类库中的静态资源:
创建默认的 ASP.NET Core Web App.
dotnet new webapp -o WebApp1
创建一个 Razor 类库并从 Web 应用程序引用它.
- dotnet new razorclasslib -o RazorLib1
- dotnet add WebApp1 reference RazorLib1
将 wwwroot 文件夹添加到 Razor 类库, 并包含一个 JavaScript 文件, 该文件将简单消息记录到控制台.
- cd RazorLib1
- mkdir wwwroot
hello.JS
console.log("Hello from RazorLib1!");
从 Web 应用程序中的 Index.cshtml 引用脚本文件.
<script src="_content/RazorLib1/hello.js"></script>
运行应用程序并在浏览器控制台中查找输出.
Hello from RazorLib1!
项目现在默认使用 System.Text.JSON
现在, 新的 ASP.NET Core 项目将默认使用 System.Text.JSON 进行 JSON 处理. 在此版本中, 我们从项目模板中删除了 JSON.NET(Newtonsoft.JSON). 要启用对使用 JSON.NET 的支持, 请将 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包添加到项目中, 并 AddNewtonsoftJson()在 Startup.ConfigureServices 方法中添加对以下代码的调用. 例如:
- services.AddMvc()
- .AddNewtonsoftJson();
证书和 Kerberos 身份验证
预览 6 为 ASP.NET Core 带来了证书和 Kerberos 身份验证.
证书身份验证要求您将服务器配置为接受证书, 然后在 Startup.Configure 中添加身份验证中间件和在 Startup.ConfigureServices 中配置证书身份验证服务.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddAuthentication(
- CertificateAuthenticationDefaults.AuthenticationScheme)
- .AddCertificate();
- // All the other service configuration.
- }
- public void Configure(IApplicationBuilder App, IHostingEnvironment env)
- {
- App.UseAuthentication();
- // All the other App configuration.
- }
证书身份验证选项包括接受自签名证书, 检查证书吊销以及检查提供的证书中是否包含正确的使用标记的功能. 默认用户主体是从证书属性构造的, 其中包含一个允许您补充或替换主体的事件. 有关如何为证书身份验证配置公共主机的所有选项和说明, 请参阅文档.
我们还将 "Windows 身份验证" 扩展到 Linux 和 macOS 上. 以前, 此身份验证类型仅限于 IIS 和 HttpSys, 但现在 Kestrel 可以使用 Microsoft.AspNetCore.Authentication.Negotiate nuget 包在 Windows,Linux 和 macOS 上为 Windows 域加入的主机使用 Negotiate,Kerberos 和 NTLM. 与配置身份验证应用程序范围的其他身份验证服务一样, 然后配置服务:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
- .AddNegotiate();
- }
- public void Configure(IApplicationBuilder App, IHostingEnvironment env)
- {
- App.UseAuthentication();
- // All the other App configuration.
- }
必须正确配置主机. Windows 主机必须将 SPN 添加到托管应用程序的用户帐户. 必须将 Linux 和 macOS 计算机加入域, 然后必须为 Web 进程创建 SPN, 以及在主机上生成和配置的文件. 文档中给出了完整的说明.
SignalR 自动重新连接
此预览版本现已通过 NPM install @aspnet/signalr@next 和. NET Core SignalR Client 方式进行提供, 包括一个新的自动重新连接功能. 在这个版本中, 我们已经将 withAutomaticReconnect()方法添加到了 HubConnectionBuilder. 默认情况下, 客户端将尝试立即重新连接, 并在 2,10 和 30 秒后重新连接. 参与自动重新连接是可选的, 但通过这种新方法很简单.
- const connection = new signalR.HubConnectionBuilder()
- .withUrl("/chatHub")
- .withAutomaticReconnect()
- .build();
通过将一系列基于毫秒的持续时间传递给该方法, 您可以非常精细地了解重新连接尝试如何随时间发生.
- .withAutomaticReconnect([0, 3000, 5000, 10000, 15000, 30000])
- //.withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior
或者, 您可以传递自定义重新连接策略的实现, 该策略可以让您完全控制.
如果 30 秒后重新连接失败(或您设置的最大值), 客户端会假定连接处于脱机状态, 并停止尝试重新连接. 在这些重新连接尝试期间, 您将希望更新应用程序 UI, 以向用户提供尝试重新连接的提示.
重新连接事件处理程序
为了简化这一过程, 我们将 SignalR 客户端 API 扩展为包含 onreconnecting 和 onreconnected 事件处理程序. 第一个处理程序 onreconnecting 为开发人员提供了一个禁用 UI 或让用户知道应用程序处于脱机状态的好机会.
- connection.onreconnecting((error) => {
- const status = `Connection lost due to error "${error}". Reconnecting.`;
- document.getElementById("messageInput").disabled = true;
- document.getElementById("sendButton").disabled = true;
- document.getElementById("connectionStatus").innerText = status;
- });
同样, onreconnected 处理程序使开发人员有机会在重新建立连接后更新 UI.
- connection.onreconnected((connectionId) => {
- const status = `Connection reestablished. Connected.`;
- document.getElementById("messageInput").disabled = false;
- document.getElementById("sendButton").disabled = false;
- document.getElementById("connectionStatus").innerText = status;
- });
了解有关自定义和处理重新连接的详细信息
预览版本中已经部分记录了自动重新连接. 请访问 https://aka.ms/signalr/auto-reconnect , 查看有关该主题的更深入的文档, 以及有关使用的更多示例和详细信息.
托管 gRPC 客户端
在之前的预览中, 我们依靠 Grpc.Core 库来获取客户端支持. HttpClient 在此预览中添加 HTTP / 2 支持使我们能够引入完全托管的 gRPC 客户端.
要开始使用新客户端, 请添加包引用 Grpc.NET.Client, 然后您可以创建新客户端.
- var httpClient = new HttpClient() {
- BaseAddress = new Uri("https://localhost:5001")
- };
- var client = GrpcClient.Create<GreeterClient>(httpClient);
gRPC 客户端工厂
基于我们介绍的固定模式 HttpClientFactory, 我们添加了一个 gRPC 客户端工厂, 用于在项目中创建 gRPC 客户端实例. 我们添加了两种工厂: Grpc.NET.ClientFactory 和 Grpc.AspNetCore.Server.ClientFactory.
该 Grpc.NET.ClientFactory 设计用于 non-ASP.NET 应用模型的使用 (如工人服务) 仍然使用 Microsoft.Extensions.* 原语不会对 ASP.NET 核心的依赖.
该 Grpc.NET.ClientFactory 设计用于仍使用 Microsoft.Extensions.* 基元 (不依赖于 ASP.NET 核心) 的非 ASP.NET 应用程序模型(如 Worker Services).
在执行服务到服务通信的应用程序中, 我们经常发现大多数服务器也是使用其他服务的客户端. 在这些情况下, 我们建议使用 Grpc.AspNetCore.Server.ClientFactory 它具有自动传播 gRPC 截止日期和取消令牌的功能.
要使用客户端工厂, 请在将以下代码添加到 configureServices()之前, 将适当的包引用添加到项目(Grpc.AspNetCore.Server.Factory 或 Grpc.NET.ClientFactory).
- services
- .AddGrpcClient<GreeterClient>(options =>
- {
- options.BaseAddress = new Uri("https://localhost:5001");
- });
gRPC 拦截器
gRPC 公开了一种机制来拦截客户端和服务器上的 RPC 调用. 拦截器可以与现有的 HTTP 中间件结合使用. 与 HTTP 中间件不同, 拦截器允许您在序列化之前 (在客户端上) 和反序列化之后 (在服务器上) 访问实际的请求 / 响应对象, 反之亦然. 所有中间件都在请求端的拦截器之前运行, 反之亦然.
客户端拦截器
与客户端工厂一起使用时, 可以添加客户端拦截器, 如下所示.
- services
- .AddGrpcClient<GreeterClient>(options =>
- {
- options.BaseAddress = new Uri("https://localhost:5001");
- })
- .AddInterceptor<CallbackInterceptor>();
服务器拦截器
服务器拦截器可以 ConfigureServices()如下所示进行注册.
- services
- .AddGrpc(options =>
- {
- // This registers a global interceptor
- options.Interceptors.Add<MaxStreamingRequestTimeoutInterceptor>(TimeSpan.FromSeconds(30));
- })
- .AddServiceOptions<GreeterService>(options =>
- {
- // This registers an interceptor for the Greeter service
- options.Interceptors.Add<UnaryCachingInterceptor>();
- });
有关如何编写拦截器的示例, 请查看 grpc-dotnet repo 中的这些示例.
给予反馈
我们希望您喜欢 ASP.NET Core 和 Blazor 预览版中的新功能! 请通过在 GitHub 上 https://github.com/aspnet/aspnetcore/issues 提交问题告诉我们您的想法.(再次声明, 本文大多内容翻译自: ASP.NET 首席项目经理 Daniel Roth 的介绍, 因此才会有这段话.)
感谢您试用 ASP.NET Core 和 Blazor!
来源: https://www.cnblogs.com/yilezhu/p/11031441.html