目录
.NET 7 Preview 3现已推出,其中包括对ASP.NET Core的许多重大改进。
以下是此预览版中新增功能的摘要:
- 在最少的API中支持路由处理程序过滤器
- 改进了最小路由处理程序的单元可测试性
- 在MVC和API控制器中使用TryParse绑定
- 新的重载Results.Stream()
- 在连接上使用多个流时改进了HTTP/2性能
- 测量启动时间的新ServerReady事件
- 开发者异常页面深色模式
有关为.NET 7计划的ASP.NET Core工作的更多详细信息,请参阅GitHub上的.NET 7的完整ASP.NET Core路线图。
开始使用
要开始使用.NET 7 Preview 3中的ASP.NET Core,请安装.NET 7 SDK。
如果你在Windows上使用Visual Studio,我们建议安装最新的Visual Studio 2022预览版。Visual Studio for Mac对.NET 7预览版的支持尚不可用,但即将推出。
要安装最新的.NET WebAssembly构建工具,请从提升的命令提示符处运行以下命令:
dotnet workload install wasm-tools
注意:目前不支持使用.NET 7 SDK和.NET 7 WebAssembly构建工具构建.NET 6 Blazor项目。这将在未来的.NET 7更新中解决:dotnet/runtime#65211。
升级现有项目
要将现有的ASP.NET Core应用从.NET 7 Preview 2升级到.NET 7 Preview 3:
- 将所有Microsoft.AspNetCore.*包引用更新为.7.0.0-preview.3.*
- 将所有Microsoft.Extensions.*包引用更新为.7.0.0-preview.3.*
另请参阅.NET 7的ASP.NET Core中的重大更改的完整列表。
在最少的API中支持路由处理程序过滤器
在此预览版中,我们介绍了对最小应用程序中路由处理程序中的过滤器的支持。过滤器在核心路由处理程序逻辑之前执行,可用于检查和修改处理程序参数或拦截处理程序执行。
过滤器可以使用多种策略注册到处理程序上。例如,您可以使用RouteHandlerFilterDelegate和AddFilter扩展方法注册过滤器,如下所示:
string HelloName(string name) => $"Hello, {name}!";
app.MapGet("/hello/{name}", HelloName)
.AddFilter(async (routeHandlerInvocationContext, next) =>
{
var name = (string) routeHandlerInvocationContext.Parameters[0];
if (name == "Bob")
{
return Results.Problem("No Bob's allowed");
}
return await next(routeHandlerInvocationContext);
});
过滤器也可以通过过滤器工厂策略注册,该策略允许访问RouteHandlerContext, RouteHandlerContext允许访问与处理程序关联的MethodInfo和注册在端点上的元数据。
app.MapGet("/hello/{name}", HelloName)
.AddFilter((routeHandlerContext, next) =>
{
var parameters = routeHandlerContext.MethodInfo.GetParameters();
var hasCorrectSignature = parameters.Length == 1 && parameters[0].ParameterType == typeof(string);
return async (routeHandlerInvocationContext) =>
{
if (hasCorrectSignature)
{
var name = (string) routeHandlerInvocationContext.Parameters[0];
if (name == "Bob")
{
return Results.Problem("No Bob's allowed");
}
}
return await next(routeHandlerInvocationContext);
};
});
最后,过滤器可以实现IRouteHandlerFilter接口并从DI中解析或作为实例传递。
app.MapGet("/hello/{name}", HelloName)
.AddFilter<MyFilter>();
改进了最小路由处理程序的单元可测试性
IResult实现类型现在在命名空间Microsoft.AspNetCore.Http中以后缀HttpResult (OkObjectHttpResult, ProblemHttpResult等) 公开可用。使用这些类型,您现在可以在使用命名方法而不是lambda时更轻松地对最小路由处理程序进行单元测试。
[Fact]
public async Task GetTodoReturnsTodoFromDatabase()
{
var todo = new Todo { Id = 42, Name = "Improve Results testability!" };
var mockDb = new MockTodoDb(new[] { todo });
var result = (OkObjectHttpResult)await TodoEndpoints.GetTodo(mockDb, todo.Id);
//Assert
Assert.Equal(200, result.StatusCode);
var foundTodo = Assert.IsAssignableFrom<Models.Todo>(result.Value);
Assert.Equal(id, foundTodo.Id);
}
[Fact]
public void CreateTodoWithValidationProblems()
{
//Arrange
var newTodo = default(Todo);
var mockDb = new MockTodoDb();
//Act
var result = TodoEndpoints.CreateTodo(mockDb, newTodo);
//Assert
var problemResult = Assert.IsAssignableFrom<ProblemHttpResult>(result);
Assert.NotNull(problemResult.ProblemDetails);
Assert.Equal(400, problemResult.StatusCode);
}
在MVC和API控制器中使用TryParse绑定
您现在可以使用TryParse具有以下签名之一的方法绑定控制器操作参数值:
public static bool TryParse(string value, T out result);
public static bool TryParse(string value, IFormatProvider provider, T out result);
例如,以下控制器中的Get操作使用参数类型上的TryParse方法绑定来自查询字符串的数据:
public class TryParseController : ControllerBase
{
// GET /tryparse?data=MyName
[HttpGet]
public ActionResult Get([FromQuery]CustomTryParseObject data) => Ok();
public class CustomTryParseObject
{
public string? Name { get; set; }
public static bool TryParse(string s, out CustomTryParseObject result)
{
if (s is null)
{
result = default;
return false;
}
result = new CustomTryParseObject { Name = s };
return true;
}
}
}
新的Results.Stream()重载
我们引入了新的Results.Stream(...)重载来适应需要访问底层HTTP响应流而不进行缓冲的场景。这些重载还改进了API想要将数据流式传输到HTTP响应流的情况,例如从Azure Blob存储。下面的示例演示了使用ImageSharp进行图像处理时的使用Results.Stream()。
app.MapGet("/process-image", async (HttpContext http) =>
{
using var image = await Image.LoadAsync("puppy.jpeg");
int width = image.Width / 2;
int height = image.Height / 2;
image.Mutate(x => x.Resize(width, height));
http.Response.Headers.CacheControl = $"public,max-age={FromHours(24).TotalSeconds}";
return Results.Stream(stream => image.SaveAsync(stream, PngFormat.Instance), "image/png");
});
在连接上使用多个流时改进了HTTP/2性能
我们对HTTP/2帧编写代码进行了更改,以在多个流尝试在单个HTTP/2连接上写入数据时提高性能。我们现在将TLS工作分派到线程池,并更快地释放其他流可以获取以写入其数据的写锁。在争用此写锁的情况下,等待时间的减少可以显着提高性能。在单个连接(使用TLS)上具有70个流的gRPC基准测试显示,随着这一变化,每秒请求数(RPS)提高了约15%。
测量启动时间的新ServerReady事件
如果您使用EventSource度量/诊断并想要测量ASP.NET Core应用程序的启动时间,您现在可以使用Microsoft.AspNetCore.Hosting源中的新ServerReady事件,该事件代表您的服务器启动并运行的时间点。
开发者异常页面深色模式
ASP.NET Core开发人员异常页面现在支持暗模式:
感谢@poke贡献了这一改进!
给予反馈
我们希望您喜欢.NET 7中的ASP.NET Core预览版。通过在GitHub上提交问题,让我们知道您对这些新改进的看法。
感谢您试用ASP.NET Core!
https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-3/