ASP.NET Core 在 .NET 6 Preview 2 中的更新
原文:《ASP.NET Core updates in .NET 6 Preview 2》,作者 Daniel Roth
.NET 6 预览版 2 现已推出,其中包括许多对 ASP.NET Core 的新改进。
以下是本次预览版的新内容:
- Razor 编译器更新为使用 Source Generators
- Blazor 支持自定义事件参数
- 增加 MVC 视图和 Razor 页面的 CSS 隔离
- Blazor 支持从祖先组件中推断组件的泛型类型
- Blazor 应用程序支持保留预渲染时的状态
- SignalR – 支持 Nullable 标注
马上开始
想开始在 .NET 6 Preview 2 中使用 ASP.NET Core,请先安装 .NET 6 SDK。
如果您正在 Windows 上使用 Visual Studio,我们建议安装 Visual Studio 2019 16.10 的最新预览版。如果您在 macOS 上,我们建议安装 Visual Studio 2019 for Mac 8.10 的最新预览版。
升级现有项目
要将现有的 ASP.NET Core 应用程序从 .NET 6 Preview 1升级到.NET 6 Preview 2,您需要:
- 更新所有 Microsoft.AspNetCore.* 包的引用到 6.0.0-preview.2.*.
- 更新所有 Microsoft.Extensions.* 包的引用到 6.0.0-preview.2.*.
再查看完整的 ASP.NET Core 在 .NET 6 中的破坏性改动列表。
Razor 编译器更新为使用 Source Generators
我们在这个预览版中更新了 Razor 编译器,使用 C# Source Generators来实现。Source Generators 在编译过程中运行,并能检查正在编译的内容,以生成额外的文件,与项目的其余部分一起编译。我们使用 Source Generators 简化了 Razor 编译器,并显著加快了构建的时间。
下图显示了使用新的 Razor 编译器构建默认的 Blazor Server 和 MVC 模板时的构建时间改进。
Blazor 支持自定义事件参数
Blazor 对自定义事件的支持现已扩展到支持自定义事件参数。这允许通过自定义事件向 .NET 事件处理程序传递任意数据。
例如,您可能希望在用户粘贴文本的同时接收剪贴板粘贴事件。要做到这一点,首先要为您的事件声明一个自定义的名称,以及一个 .NET ,该类将持有该事件的事件参数,通过添加以下类到您的项目中:
[EventHandler("oncustompaste", typeof(CustomPasteEventArgs), enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
// 这个静态类不需要包含任何成员。
// 它只是一个让我们可以把 [EventHandler] 属性放在 Razor 编译器上配置事件类型的地方。
// 这样将影响编译器的输出以及编辑器中的代码完成。
}
public class CustomPasteEventArgs : EventArgs
{
// 这些属性的数据将由自定义的 JavaScript 逻辑提供。
public DateTime EventTimestamp { get; set; }
public string PastedData { get; set; }
}
一旦这些都到位了,您就会在您的 Razor 组件中得到一个叫做 @oncustompaste
的新事件的智能提醒。例如,在 Index.razor
中,您可以按以下方式使用它:
@page "/"
<p>Try pasting into the following text box:</p>
<input @oncustompaste="HandleCustomPaste" />
<p>@message</p>
@code {
string message;
void HandleCustomPaste(CustomPasteEventArgs eventArgs)
{
message = $"At {eventArgs.EventTimestamp.ToShortTimeString()}, you pasted: {eventArgs.PastedData}";
}
}
然而,如果您现在实际运行代码,事件将不会触发。因为还剩下一个步骤,就是添加一些 JavaScript 代码,实际为您的新 EventArgs
子类提供数据。在您的 index.html
或 _Host.cshtml
文件中,添加以下内容:
<!-- 您需要将这段代码直接添加到 blazor.server.js 或 blazor.webassembly.js 的 <script> 标签后面。-->
<script>
Blazor.registerCustomEventType('custompaste', {
browserEventName: 'paste',
createEventArgs: event => {
// 这个例子只处理粘贴文本,但你可以使用任意的 JavaScript API
// 来处理用户粘贴其他类型的数据,如图片。
return {
eventTimestamp: new Date(),
pastedData: event.clipboardData.getData('text')
};
}
});
</script>
这是告诉浏览器,每当本地粘贴事件发生时,它也应该引发一个自定义粘贴事件,并使用您的自定义逻辑提供事件参数数据。请注意,事件名称的约定在 .NET(事件名称前缀为on)和 JavaScript(事件名称没有任何前缀)之间有所不同。
增加 MVC 视图和 Razor 页面的 CSS 隔离
现在,MVC视图 和 Razor 页面跟 Blazor 组件一样支持 CSS 隔离。想要添加一个视图或页面特定的 CSS 文件,只需添加一个与 .cshtml
文件名称相匹配的 .cshtml.css
文件即可。
Index.cshtml.css
h1 {
color: red;
}
在你的布局中添加一个链接到 {项目名}.styles.css 来引用捆绑的样式。
<link rel="stylesheet" href="MyWebApp.styles.css" />
然后,这些样式将只应用于各自的视图和页面。
Blazor 支持从祖先组件中推断组件的泛型类型
在使用 Blazor 的泛型组件(如 Grid<TItem>
或 ListView<TItem>
)时,Blazor 通常可以根据传递给组件的参数来推断泛型类型参数,因此您不必明确指定它们。但在更复杂的组件中,您可能会有多个泛型组件一起使用,而这些组件的类型参数是要匹配的,比如 Grid<TItem>
和 Column<TItem>
。在这些复合场景中,泛型类型参数通常需要显式指定,就像这样:
<Grid Items="@people">
<Column TItem="Person" Name="Full name">@context.FirstName @context.LastName</Column>
<Column TItem="Person" Name="E-mail address">@context.Email</Column>
</Grid>
但你真正想做的是:
<Grid Items="@people">
<Column Name="Full name">@context.FirstName @context.LastName</Column>
<Column Name="E-mail address">@context.Email</Column>
</Grid>
有必要在每个 <Column>
上重新指定 TItem
,因为每个 <Column>
都被视为一个独立的组件,没有其他方法知道它应该与什么类型的数据一起工作。
在 .NET 6 Preview 2 中,Blazor 可以从祖先组件中推断出泛型类型参数。祖先组件必须选择性地加入这种行为,使用 [CascadingTypeParameter]
特性(attribute)来通过名称将类型参数级联到后代。这个特性(attribute)允许泛型类型推断出,对于有同名类型参数的子代,可以自动使用指定的类型参数。
例如,你可以定义像这样的 Grid
和 Column
组件:
Grid.razor
@typeparam TItem
@attribute [CascadingTypeParameter(nameof(TItem))]
...
@code {
[Parameter] public IEnumerable<TItem> Items { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
}
Column.razor
@typeparam TItem
...
@code {
[Parameter] public string Title { get; set; }
}
然后你可以像这样使用 Grid
和 Column
组件:
<Grid Items="@GetItems()">
<Column Title="Product name" />
<Column Title="Num sales" />
</Grid>
@code {
IEnumerable<SaleRecord> GetItems() { ... }
}
注意:Visual Studio Code 中的 Razor 支持尚未更新以支持该功能,因此即使项目正确构建,你也可能遇到误判的错误提醒。这将在即将发布的工具版本中解决。
Blazor 应用程序支持保留预渲染时的状态
Blazor 应用程序可从服务端进行预渲染,以加快应用程序可感知的加载时间。当应用程序在后台进行交互性设置时,可立即渲染预渲染的 HTML。但是,预渲染期间使用的任何状态都会丢失,必须在应用程序完全加载时重新创建。如果异步设置任何状态,那么当预渲染的 UI 被临时占位符替换,然后再次完全渲染时,UI可能会闪烁。
为了解决这个问题,我们增加了新的 <preserve-component-state />
tag helper,它可以支持把状态持久化到预渲染页面。在你的应用程序中,你可以使用新的 ComponentApplicationState
服务来决定你要持久化的状态。当状态即将被持久化到预渲染页面中时,ComponentApplicationState.OnPersisting
事件会被触发。然后你就可以在初始化你的组件时恢复(retrieved)任何已被持久化的状态。
下面的示例展示了如何在预渲染期间持久化默认的 FetchData
组件中的天气预报,然后在 Blazor
服务端应用程序中恢复状态以初始化该组件。
_Host.cshtml
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
...
@* 当所有组件调用后持久化组件状态 *@
<persist-component-state />
</body>
FetchData.razor
@page "/fetchdata"
@implements IDisposable
@inject ComponentApplicationState ApplicationState
...
@code {
protected override async Task OnInitializedAsync()
{
ApplicationState.OnPersisting += PersistForecasts;
if (!ApplicationState.TryRedeemPersistedState("fetchdata", out var data))
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
else
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
};
forecasts = JsonSerializer.Deserialize<WeatherForecast[]>(data, options);
}
}
private Task PersistForecasts()
{
ApplicationState.PersistAsJson("fetchdata", forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
ApplicationState.OnPersisting -= PersistForecasts;
}
}
注意:这个预览版中提供了一个
TryRedeemFromJson<T>
辅助方法,但有一个已知的问题,将会在未来的更新中解决。为了解决这个问题,请先使用TryRedeemPersistedState
和手动JSON反序列化,如上例所示。
通过使用与预渲染时相同的状态来初始化你的组件,任何昂贵的初始化步骤都只需要执行一次。新渲染的 UI 也与预渲染的 UI 相匹配,因此不会发生闪烁。
SignalR - Nullable 注解
ASP.NET Cpre SignalR 客户端包中已经启用 Nullability。这意味着,当您 启用 Nullability时,C# 编译器将根据您在 SignalR API 中对空值的处理提供适当的反馈。在 .NET 5 中,SignalR 服务器已经更新了 Nullability,但在 .NET 6 中做了一些修改。您可以在 dotnet/aspnetcore #27389 中跟踪 ASP.NET Core 对 Nullable 注解的支持。
给予反馈
我们希望您喜欢这个 .NET 6 中 ASP.NET Core 的预览版。我们渴望听到您对这个版本的体验。请在 GitHub 上提交问题,让我们知道你的想法。
感谢你试用 ASP.NET Core!
ASP.NET Core 在 .NET 6 Preview 2 中的更新的更多相关文章
- ASP.NET Core在 .NET Core 3.1 Preview 1中的更新
.NET Core 3.1 Preview 1现在可用.此版本主要侧重于错误修复,但同时也包含一些新功能. 这是此版本的ASP.NET Core的新增功能: 对Razor components的部分类 ...
- [翻译]ASP.NET Core在 .NET 5 Preview 7的更新
.NET 5 Preview 7现在可以用了,可以进行评估了.这是此版本中的新增功能: Blazor WebAssembly应用程序现在针对.NET 5 更新了Blazor WebAssembly的调 ...
- Asp.net Core 1.0.1升级到Asp.net Core 1.1.0 Preview版本发布到Windows Server2008 R2 IIS中的各种坑
Asp.net Core 1.0.1升级到Asp.net Core 1.1.0后,程序无法运行了 解决方案:在project.json中加入runtime节点 "runtimes" ...
- ASP.NET Core 一步步搭建个人网站(持续更新中~~~)
摘要 ASP.NET Core2.0发布有一阵子了,这是.NET 开源跨平台的一个重大里程碑, 也意味着比1.0版本要更加成熟.目前.net core具有开源.跨平台.灵活部署.模块化架构等等特性,吸 ...
- 【ASP.NET Core】如何隐藏响应头中的 “Kestrel”
全宇宙人民都知道,ASP.NET Core 应用是不依赖服务器组件的,因此它可以独立运行,一般是使用支持跨平台的 Kestrel 服务器(当然,在 Windows 上还可以考虑用 HttpSys,但要 ...
- Asp.Net Core&Docker部署到树莓派3B中
花了一点时间将吃灰数月的树莓派装上了Docker,并在容器中部署了一个Asp.Net Core应用程序,通过花生壳映射树莓派中的程序,可以使用外网访问树莓派,玩起来很有意思(外网访问地址:http:/ ...
- 学习ASP.NET Core Razor 编程系列十一——把新字段更新到数据库
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- 【Asp.Net Core】在Visual Studio 2017中使用Asp.Net Core构建Angular4应用程序
前言 Visual Studio 2017已经发布了很久了.做为集成了Asp.Net Core 1.1的地表最强IDE工具,越来越受.NET系的开发人员追捧. 随着Google Angular4的发布 ...
- Asp.Net Core WebAPI+PostgreSQL部署在Docker中
PostgreSQL是一个功能强大的开源数据库系统.它支持了大多数的SQL:2008标准的数据类型,包括整型.数值值.布尔型.字节型.字符型.日期型.时间间隔型和时间型,它也支持存储二进制的大对像, ...
随机推荐
- 牛客网多校第5场 I vcd 【树状数组+离散化处理】【非原创】
题目:戳这里 学习博客:戳这里 作者:阿狸是狐狸啦 n个点,一个点集S是好的,当且仅当对于他的每个子集T,存在一个右边无限延长的矩形,使的这个矩形包含了T,但是和S-T没有交集. 求有多少个这种集合. ...
- HDU - 4725 The Shortest Path in Nya Graph 【拆点 + dijkstra】
This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just ...
- C++含有无符号类型的表达式的计算
unsigned u=10; int i=-42; cout<<i+i<<endl; cout<<u+i<<endl; 在第二个输出表达式中,相加前首先 ...
- Linux内核实现透视---硬中断
Linux的中断处理是驱动中比较重要的一部分内容,要清楚具体的实现才能更好的理解而不是靠记住别人理解后总结的规律,所以今天就打算从从源码来学习一下Linux内核对于中断处理过程,设计中断子系统的初始化 ...
- MDK5生成BIn文件的方法
配置MDK5 生成bin文件的 第一步:方法打开option for Target 第二步:选择 user 第三步:找到After Build/Rebuild 第四步:勾选run,点击文件选择小图标选 ...
- matplotlib 单figure多图
method 1 import numpy as np import matplotlib.pyplot as plt fg, axes = plt.subplots(1, 2, figsize=(1 ...
- Apple Watch Series 6 屏幕误触放大后无法还原问题和解决方案
Apple Watch Series 6 屏幕误触放大后无法还原问题和解决方案 shit Apple,只能放大,不能缩小! 解决方案 关闭缩放功能 https://support.apple.com/ ...
- nodejs 调用win32 api
video 教程文件 win32 api >node -v v12.16.1 >npm install -g node-gyp >npm i @saleae/ffi >node ...
- 大数据开发-linux下常见问题详解
1.user ss is currently user by process 3234 问题原因:root --> ss --> root 栈递归一样 解决方式:exit 退出当前到ss再 ...
- redis五种数据类型的应用
redis的五种数据类型和使用场景 string类型 string类型多用于缓存 set key value(value可以为json字符串) setnx多用于分布式锁(后面详细整理) 计数器 inc ...