Новые возможности в ASP.NET Core 7.0
В этой статье описываются наиболее важные изменения в ASP.NET Core 7.0 со ссылками на соответствующую документацию.
ПО промежуточного слоя для ограничения скорости в ASP.NET Core
ПО промежуточного слоя Microsoft.AspNetCore.RateLimiting
предоставляет ПО промежуточного слоя для ограничения скорости. Приложения настраивают политики ограничения скорости, а затем присоединяют политики к конечным точкам. Дополнительные сведения см. в статье ПО промежуточного слоя для ограничения скорости в ASP.NET Core.
Проверка подлинности использует одну схему в качестве DefaultScheme
В рамках работы по упрощению проверки подлинности при регистрации только одной схемы проверки подлинности она автоматически используется в качестве DefaultScheme и не нужно указывать. Дополнительные сведения см. в разделе DefaultScheme.
MVC и Razor Pages
Поддержка моделей, допускающих значение NULL, в представлениях MVC и Razor Pages
Модели страниц или представлений, допускающих значение NULL, поддерживаются для улучшения работы при проверке состояния NULL в приложениях ASP.NET Core:
@model Product?
Привязка с помощью IParsable<T>.TryParse
в контроллерах API и MVC
API IParsable<TSelf>.TryParse
поддерживает привязку значений параметров действий контроллера. Дополнительные сведения см. в разделе Привязка с помощью IParsable<T>.TryParse
.
Настройка значения согласия cookie
В версиях ASP.NET Core, предшествующих 7, при проверке согласия cookie используется значение yes
cookie, чтобы указать согласие. Теперь можно указать значение, представляющее согласие. Например, можно использовать true
вместо yes
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.ConsentCookieValue = "true";
});
var app = builder.Build();
Дополнительные сведения см. в статье о настройке значения согласия cookie.
Контроллеры API
Привязка параметров с помощью внедрения зависимостей в контроллерах API
Привязка параметров для действий контроллера API позволяет привязать параметры с помощью внедрения зависимостей при настройке типа в качестве службы. Это означает, что больше не требуется явно применять атрибут [FromServices]
к параметру. В следующем коде оба действия возвращают время:
[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
public ActionResult GetWithAttribute([FromServices] IDateTime dateTime)
=> Ok(dateTime.Now);
[Route("noAttribute")]
public ActionResult Get(IDateTime dateTime) => Ok(dateTime.Now);
}
В редких случаях автоматическое внедрение зависимостей может прервать работу приложения, если оно имеет тип, который также принимается в методах действий контроллеров API. Обычно тип во внедрении зависимостей и тип, используемый в качестве аргумента в действии контроллера API, не совпадают. Чтобы отключить автоматическую привязку параметров, задайте DisableImplicitFromServicesParameters:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddSingleton<IDateTime, SystemDateTime>();
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.DisableImplicitFromServicesParameters = true;
});
var app = builder.Build();
app.MapControllers();
app.Run();
В ASP.NET Core 7.0 типы во внедрении зависимостей проверяются при запуске приложения с помощью IServiceProviderIsService, чтобы определить, поступает ли аргумент в действии контроллера API из внедрения зависимостей или из других источников.
Новый механизм вывода источника привязки параметров действия контроллера API использует следующие правила:
- Указанный ранее
BindingInfo.BindingSource
не перезаписывается. - Назначается параметр сложного типа, зарегистрированный в контейнере внедрения зависимостей:
BindingSource.Services
. - Назначается параметр сложного типа, не зарегистрированный в контейнере внедрения зависимостей:
BindingSource.Body
. - Параметру с именем, которое появляется как значение маршрута в любом шаблоне маршрута, присваивается
BindingSource.Path
. - В качестве остальных параметров используется
BindingSource.Query
.
Имена свойств JSON в ошибках проверки
По умолчанию при возникновении ошибки проверки в результате проверки модели создается ModelStateDictionary с именем свойства в качестве ключа ошибки. Некоторые приложения, такие как одностраничные приложения, используют имена свойств JSON для ошибок проверки, созданных из веб-API. Следующий код настраивает проверку для использования SystemTextJsonValidationMetadataProvider
имен свойств JSON:
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.ModelMetadataDetailsProviders.Add(new SystemTextJsonValidationMetadataProvider());
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Следующий код настраивает проверку для использования NewtonsoftJsonValidationMetadataProvider
имени свойства JSON при использовании Json.NET:
using Microsoft.AspNetCore.Mvc.NewtonsoftJson;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.ModelMetadataDetailsProviders.Add(new NewtonsoftJsonValidationMetadataProvider());
}).AddNewtonsoftJson();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Дополнительные сведения см. в разделе "Использование имен свойств JSON в ошибках проверки"
Минимальные API
Фильтры в приложениях с минимальным API
Фильтры минимальных API позволяют разработчикам реализовать бизнес-логику, которая поддерживает следующее:
- Выполнение кода до и после запуска обработчика маршрутов.
- Проверка и изменение параметров, предоставленных при вызове обработчика маршрутов.
- Перехват ответа обработчика маршрутов.
Фильтры могут быть полезны в следующих сценариях:
- Проверка параметров и текста запросов, отправляемых в конечную точку.
- Запись сведений о запросе и ответе в журнал.
- Проверка того, что запрос предназначен для поддерживаемой версии API.
Дополнительные сведения см. в статьях "Фильтры" в приложениях API "Минимальный"
Привязка массивов и строковых значений из заголовков и строк запроса
В ASP.NET 7 поддерживается привязка строк запроса к массиву примитивных типов, массивам строк и StringValues.
// Bind query string values to a primitive type array.
// GET /tags?q=1&q=2&q=3
app.MapGet("/tags", (int[] q) =>
$"tag1: {q[0]} , tag2: {q[1]}, tag3: {q[2]}");
// Bind to a string array.
// GET /tags2?names=john&names=jack&names=jane
app.MapGet("/tags2", (string[] names) =>
$"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");
// Bind to StringValues.
// GET /tags3?names=john&names=jack&names=jane
app.MapGet("/tags3", (StringValues names) =>
$"tag1: {names[0]} , tag2: {names[1]}, tag3: {names[2]}");
Привязка строк запроса или значений заголовков к массиву сложных типов поддерживается, если для типа реализовать TryParse
. Дополнительные сведения см. в разделе Привязка массивов и строковых значений из заголовков и строк запроса.
Дополнительные сведения см. в статье о добавлении сводок или описаний конечных точек.
Привязка текста запроса в виде Stream
или PipeReader
Тело запроса может привязываться как Stream
или PipeReader
для эффективной поддержки сценариев, в которых пользователю необходимо обрабатывать данные и:
- Хранить данные в хранилище BLOB-объектов или поставить их в очередь у поставщика очередей.
- Обрабатывать хранимые данные с помощью рабочего процесса или облачной функции.
Например, данные могут быть помещены в очередь в Хранилище очередей Azure или храниться в Хранилище BLOB-объектов Azure.
Дополнительные сведения см. в статье Привязка текста запроса в качестве Stream
или PipeReader
.
Новые перегрузки Results.Stream
Мы ввели новые перегрузки Results.Stream
для сценариев, которым необходим доступ к базовому потоку HTTP-ответов без буферизации. Эти перегрузки также улучшают случаи, когда API передает данные в поток ответа HTTP, например из Хранилища BLOB-объектов Azure. В следующем примере используется ImageSharp для возврата уменьшенного размера указанного изображения:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Processing;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/process-image/{strImage}", (string strImage, HttpContext http, CancellationToken token) =>
{
http.Response.Headers.CacheControl = $"public,max-age={TimeSpan.FromHours(24).TotalSeconds}";
return Results.Stream(stream => ResizeImageAsync(strImage, stream, token), "image/jpeg");
});
async Task ResizeImageAsync(string strImage, Stream stream, CancellationToken token)
{
var strPath = $"wwwroot/img/{strImage}";
using var image = await Image.LoadAsync(strPath, token);
int width = image.Width / 2;
int height = image.Height / 2;
image.Mutate(x =>x.Resize(width, height));
await image.SaveAsync(stream, JpegFormat.Instance, cancellationToken: token);
}
Дополнительные сведения см. в разделе Примеры потоковой передачи.
Типизированные результаты для минимальных API
В .NET 6 IResult интерфейс был представлен для представления значений, возвращаемых минимальными API-интерфейсами, которые не используют неявную поддержку для сериализации возвращаемого объекта в ответ HTTP. Статический класс Results используется для создания разных объектов IResult
, которые представляют разные типы ответов. Например, установка кода статуса ответа или перенаправление на другой URL-адрес. Однако типы, реализующие IResult
, возвращаемые этими методами, были внутренними, что затрудняло проверку конкретного типа IResult
, возвращаемого методами в модульном тесте.
В .NET 7 типы, реализующие IResult
, являются общедоступными, что позволяет использовать утверждения типов при тестировании. Например:
[TestClass()]
public class WeatherApiTests
{
[TestMethod()]
public void MapWeatherApiTest()
{
var result = WeatherApi.GetAllWeathers();
Assert.IsInstanceOfType(result, typeof(Ok<WeatherForecast[]>));
}
}
Улучшенная модульная проверка для минимальных обработчиков маршрутов
IResult Типы реализации теперь общедоступны в Microsoft.AspNetCore.Http.HttpResults пространстве имен. IResult
Типы реализации можно использовать для модульного тестирования минимальных обработчиков маршрутов при использовании именованных методов вместо лямбда-кодов.
Следующий код использует Ok<TValue>
класс:
[Fact]
public async Task GetTodoReturnsTodoFromDatabase()
{
// Arrange
await using var context = new MockDb().CreateDbContext();
context.Todos.Add(new Todo
{
Id = 1,
Title = "Test title",
Description = "Test description",
IsDone = false
});
await context.SaveChangesAsync();
// Act
var result = await TodoEndpointsV1.GetTodo(1, context);
//Assert
Assert.IsType<Results<Ok<Todo>, NotFound>>(result);
var okResult = (Ok<Todo>)result.Result;
Assert.NotNull(okResult.Value);
Assert.Equal(1, okResult.Value.Id);
}
Дополнительные сведения см. в разделе IResult
"Типы реализации".
Новые интерфейсы HttpResult
Следующие интерфейсы в Microsoft.AspNetCore.Http пространстве имен предоставляют способ обнаружения IResult
типа во время выполнения, который является общим шаблоном в реализации фильтров:
- IContentTypeHttpResult
- IFileHttpResult
- INestedHttpResult
- IStatusCodeHttpResult
- IValueHttpResult
- IValueHttpResult<TValue>
Дополнительные сведения см. в интерфейсах IHttpResult.
Улучшения OpenAPI для минимальных API
пакет NuGet Microsoft.AspNetCore.OpenApi
;
Пакет Microsoft.AspNetCore.OpenApi
позволяет взаимодействовать со спецификациями OpenAPI для конечных точек. Этот пакет создает связь между моделями OpenAPI, определенными в пакете Microsoft.AspNetCore.OpenApi
, и конечными точками, определенными в минимальных API. Этот пакет предоставляет API, который проверяет параметры, ответы и метаданные конечной точки и создает тип заметки OpenAPI, подходящий для описания этой конечной точки.
app.MapPost("/todoitems/{id}", async (int id, Todo todo, TodoDb db) =>
{
todo.Id = id;
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi();
Вызов WithOpenApi
с параметрами
Метод WithOpenApi
принимает функцию, которую можно использовать для изменения заметки OpenAPI. Например, следующий код добавляет описание в первый параметр конечной точки:
app.MapPost("/todo2/{id}", async (int id, Todo todo, TodoDb db) =>
{
todo.Id = id;
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi(generatedOperation =>
{
var parameter = generatedOperation.Parameters[0];
parameter.Description = "The ID associated with the created Todo";
return generatedOperation;
});
Предоставление описаний и сводок конечных точек
Минимальные API-интерфейсы теперь поддерживают операции аннотирования с описаниями и сводками для создания спецификаций OpenAPI. Можно вызывать методы расширения WithDescription и WithSummary или использовать атрибуты [EndpointDescription] и [EndpointSummary]).
Дополнительные сведения см. в разделе OpenAPI в минимальных приложениях API
Отправка файлов с помощью IFormFile и IFormFileCollection
Минимальные API теперь поддерживают отправку файлов с применением IFormFile
и IFormFileCollection
. Следующий код использует IFormFile и IFormFileCollection, чтобы отправить файл:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapPost("/upload", async (IFormFile file) =>
{
var tempFile = Path.GetTempFileName();
app.Logger.LogInformation(tempFile);
using var stream = File.OpenWrite(tempFile);
await file.CopyToAsync(stream);
});
app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
foreach (var file in myFiles)
{
var tempFile = Path.GetTempFileName();
app.Logger.LogInformation(tempFile);
using var stream = File.OpenWrite(tempFile);
await file.CopyToAsync(stream);
}
});
app.Run();
Поддерживаются запросы на отправку файлов с проверкой подлинности посредством заголовка авторизации, сертификата клиента или заголовка cookie.
Встроенная поддержка защиты от подделки отсутствует. Однако ее можно реализовать с помощью службы IAntiforgery
.
Атрибут [AsParameters]
обеспечивает привязку параметров для списков аргументов.
Атрибут [AsParameters]
обеспечивает привязку параметров для списков аргументов. Дополнительные сведения: Привязка параметров для списков аргументов с помощью [AsParameters]
.
Минимальные API и контроллеры API
Новая служба сведений о проблеме
Служба сведений о проблеме IProblemDetailsService реализует интерфейс, который поддерживает создание сведений о проблеме для API HTTP.
Дополнительные сведения см. в разделе "Сведения о проблеме".
Группы маршрутов
Метод MapGroup расширения помогает упорядочивать группы конечных точек с общим префиксом. Это уменьшает повторяющийся код и позволяет настраивать целые группы конечных точек с одним вызовом методов, таких как RequireAuthorization и WithMetadata которые добавляют метаданные конечной точки.
Например, следующий код создает две аналогичные группы конечных точек:
app.MapGroup("/public/todos")
.MapTodosApi()
.WithTags("Public");
app.MapGroup("/private/todos")
.MapTodosApi()
.WithTags("Private")
.AddEndpointFilterFactory(QueryPrivateTodos)
.RequireAuthorization();
EndpointFilterDelegate QueryPrivateTodos(EndpointFilterFactoryContext factoryContext, EndpointFilterDelegate next)
{
var dbContextIndex = -1;
foreach (var argument in factoryContext.MethodInfo.GetParameters())
{
if (argument.ParameterType == typeof(TodoDb))
{
dbContextIndex = argument.Position;
break;
}
}
// Skip filter if the method doesn't have a TodoDb parameter.
if (dbContextIndex < 0)
{
return next;
}
return async invocationContext =>
{
var dbContext = invocationContext.GetArgument<TodoDb>(dbContextIndex);
dbContext.IsPrivate = true;
try
{
return await next(invocationContext);
}
finally
{
// This should only be relevant if you're pooling or otherwise reusing the DbContext instance.
dbContext.IsPrivate = false;
}
};
}
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapGet("/", GetAllTodos);
group.MapGet("/{id}", GetTodo);
group.MapPost("/", CreateTodo);
group.MapPut("/{id}", UpdateTodo);
group.MapDelete("/{id}", DeleteTodo);
return group;
}
В этом сценарии можно использовать относительный адрес заголовка Location
201 Created
в результате:
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();
return TypedResults.Created($"{todo.Id}", todo);
}
Первая группа конечных точек будет соответствовать только запросам, префиксным и /public/todos
доступным без какой-либо проверки подлинности. Вторая группа конечных точек будет соответствовать только запросам, префиксным и /private/todos
требующим проверки подлинности.
Фабрика QueryPrivateTodos
фильтров конечных точек — это локальная функция, которая изменяет параметры обработчика TodoDb
маршрутов, чтобы разрешить доступ к частным данным и хранить данные о частных объектах.
Группы маршрутов также поддерживают вложенные группы и сложные шаблоны префикса с параметрами маршрута и ограничениями. В следующем примере обработчик маршрутов, сопоставленный с user
группой, может записывать {org}
параметры маршрута, {group}
определенные в префиксах внешней группы.
Префикс также может быть пустым. Это может быть полезно для добавления метаданных конечной точки или фильтров в группу конечных точек без изменения шаблона маршрута.
var all = app.MapGroup("").WithOpenApi();
var org = all.MapGroup("{org}");
var user = org.MapGroup("{user}");
user.MapGet("", (string org, string user) => $"{org}/{user}");
Добавление фильтров или метаданных в группу ведет себя так же, как и их отдельно к каждой конечной точке перед добавлением дополнительных фильтров или метаданных, которые могли быть добавлены во внутреннюю группу или определенную конечную точку.
var outer = app.MapGroup("/outer");
var inner = outer.MapGroup("/inner");
inner.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/inner group filter");
return next(context);
});
outer.AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("/outer group filter");
return next(context);
});
inner.MapGet("/", () => "Hi!").AddEndpointFilter((context, next) =>
{
app.Logger.LogInformation("MapGet filter");
return next(context);
});
В приведенном выше примере внешний фильтр регистрирует входящий запрос до внутреннего фильтра, даже если он был добавлен вторым. Так как фильтры были применены к разным группам, порядок их добавления относительно друг друга не имеет значения. Фильтры заказов добавляются, если они применяются к той же группе или определенной конечной точке.
Запрос, который /outer/inner/
будет регистрировать следующее:
/outer group filter
/inner group filter
MapGet filter
gRPC;
Транскодирование JSON
Перекодирование gRPC JSON — это расширение для ASP.NET Core, которое создает API JSON RESTful для служб gRPC. Транскодирование JSON gRPC позволяет:
- Приложениям вызывать службы gRPC, используя следующие привычные понятия HTTP.
- ASP.NET приложения Core gRPC для поддержки API gRPC и RESTful JSON без репликации функций.
- Экспериментальная поддержка создания OpenAPI из транскодированных API RESTful путем интеграции с Swashbuckle.
Дополнительные сведения см. в статье о транскодирования json gRPC в приложениях ASP.NET Core gRPC и использовании OpenAPI с транскодированием json gRPC ASP.NET Core.
Проверки работоспособности gRPC в ASP.NET Core
Протокол проверки работоспособности gRPC является стандартом для передачи сведений о работоспособности серверных приложений gRPC. Приложение предоставляет проверки работоспособности в качестве службы gRPC. Они обычно используются с внешней службой мониторинга для проверки состояния приложения.
gRPC ASP.NET Core добавил встроенную поддержку проверок работоспособности gRPC с пакетом Grpc.AspNetCore.HealthChecks
. Результаты проверок работоспособности .NET передаются вызывающим объектам.
Дополнительные сведения см. в разделе проверки работоспособности gRPC в ASP.NET Core.
Улучшена поддержка учетных данных для звонков
Учетные данные вызова — это рекомендуемый способ настроить клиент gRPC для отправки маркера проверки подлинности на сервер. Клиенты gRPC поддерживают две новые функции, которые упрощают использование учетных данных вызова:
- Поддержка учетных данных вызова с помощью соединений с открытым текстом. Ранее вызов gRPC отправлял только учетные данные вызова, если подключение было защищенно с помощью TLS. Новый параметр
GrpcChannelOptions
, вызываемыйUnsafeUseInsecureChannelCallCredentials
, позволяет настроить это поведение. Существуют последствия для защиты подключения с помощью TLS. - Вызывается новый метод
AddCallCredentials
с помощью клиентской фабрики gRPC.AddCallCredentials
— это быстрый способ настройки учетных данных вызова для клиента gRPC и хорошо интегрируется с внедрением зависимостей (DI).
Следующий код настраивает клиентную фабрику gRPC для отправки Authorization
метаданных:
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.AddCallCredentials((context, metadata) =>
{
if (!string.IsNullOrEmpty(_token))
{
metadata.Add("Authorization", $"Bearer {_token}");
}
return Task.CompletedTask;
});
Дополнительные сведения см. в разделе "Настройка маркера носителя с помощью клиентской фабрики gRPC".
SignalR
Получение результатов от клиента
Теперь сервер поддерживает запрос результатов от клиента. Для этого требуется, чтобы сервер использовал ISingleClientProxy.InvokeAsync
, а клиент возвращал результат от своего обработчика .On
. Строго типизированные концентраторы также могут возвращать значения из методов интерфейса.
Дополнительные сведения см. в разделе Получение результатов от клиента.
Внедрение зависимостей для методов концентратора SignalR
Методы концентратора SignalR теперь поддерживают внедрение служб посредством внедрения зависимостей.
Конструкторы концентратора могут принимать службы от внедрения зависимостей в качестве параметров, которые можно хранить в свойствах класса для использования в методе концентратора. Дополнительные сведения см. в разделе Внедрение служб в концентратор.
Blazor
Обработка событий изменения расположения и состояния навигации
В .NET 7 Blazor поддерживает изменение расположения событий и поддержание состояния навигации. Это позволяет предупреждать пользователей о несохраненных работах или выполнять связанные действия при выполнении пользователем навигации по страницам.
Дополнительные сведения см. в следующих разделах статьи "Маршрутизация и навигация ".
Пустые Blazor шаблоны проектов
Blazor имеет два новых шаблона проекта для запуска с пустого листа. Новые Blazor Server шаблоны проектов App Empty иBlazor WebAssembly App Empty похожи на их непустые аналоги, но без примера кода. Эти пустые шаблоны включают только базовую home страницу, и мы удалили начальную загрузку, чтобы начать с другой платформы CSS.
Дополнительные сведения см. в следующих статьях:
Пользовательские элементы Blazor
Пакет Microsoft.AspNetCore.Components.CustomElements
позволяет создавать пользовательские элементы BlazorDOM на основе стандартов.
Дополнительные сведения см. в статье Компоненты Razor ASP.NET Core.
Модификаторы привязки (@bind:after
, @bind:get
, @bind:set
)
Внимание
В @bind:after
//@bind:get
@bind:set
настоящее время функции получают дополнительные обновления. Чтобы воспользоваться преимуществами последних обновлений, убедитесь, что вы установили последний пакет SDK.
Использование параметра обратного вызова события ([Parameter] public EventCallback<string> ValueChanged { get; set; }
) не поддерживается. Вместо этого передайте Actionметод @bind:set
/@bind:after
-returning или Task-returning.
Дополнительные сведения см. на следующих ресурсах:
В .NET 7 можно запустить асинхронную логику после завершения события привязки с помощью нового @bind:after
модификатора. В следующем примере PerformSearch
асинхронный метод выполняется автоматически после обнаружения любых изменений в тексте поиска:
<input @bind="searchText" @bind:after="PerformSearch" />
@code {
private string searchText;
private async Task PerformSearch()
{
...
}
}
В .NET 7 также проще настроить привязку для параметров компонента. Компоненты могут поддерживать двусторонняя привязка данных, определяя пару параметров:
@bind:get
: указывает значение для привязки.@bind:set
: указывает обратный вызов при изменении значения.
@bind:get
Модификаторы и @bind:set
модификаторы всегда используются вместе.
Примеры:
@* Elements *@
<input type="text" @bind="text" @bind:after="() => { }" />
<input type="text" @bind:get="text" @bind:set="(value) => { }" />
<input type="text" @bind="text" @bind:after="AfterAsync" />
<input type="text" @bind:get="text" @bind:set="SetAsync" />
<input type="text" @bind="text" @bind:after="() => { }" />
<input type="text" @bind:get="text" @bind:set="(value) => { }" />
<input type="text" @bind="text" @bind:after="AfterAsync" />
<input type="text" @bind:get="text" @bind:set="SetAsync" />
@* Components *@
<InputText @bind-Value="text" @bind-Value:after="() => { }" />
<InputText @bind-Value:get="text" @bind-Value:set="(value) => { }" />
<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />
<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />
<InputText @bind-Value="text" @bind-Value:after="() => { }" />
<InputText @bind-Value:get="text" @bind-Value:set="(value) => { }" />
<InputText @bind-Value="text" @bind-Value:after="AfterAsync" />
<InputText @bind-Value:get="text" @bind-Value:set="SetAsync" />
@code {
private string text = "";
private void After(){}
private void Set() {}
private Task AfterAsync() { return Task.CompletedTask; }
private Task SetAsync(string value) { return Task.CompletedTask; }
}
Дополнительные сведения о компоненте InputText
см. в разделе ASP.NET Основные Blazor входные компоненты.
улучшения Горячая перезагрузка
В .NET 7 поддержка Горячая перезагрузка включает следующее:
- Компоненты сбрасывают параметры в значения по умолчанию при удалении значения.
- Blazor WebAssembly:
- Добавьте новые типы.
- Добавьте вложенные классы.
- Добавьте статические и экземплярные методы в существующие типы.
- Добавьте статические поля и методы в существующие типы.
- Добавьте статические лямбда-выражения в существующие методы.
- Добавьте лямбда-выражения, которые записываются
this
в существующие методы, которые уже записаныthis
ранее.
Динамические запросы проверки подлинности с помощью MSAL в Blazor WebAssembly
Новые возможности .NET 7 Blazor WebAssembly поддерживают создание динамических запросов проверки подлинности во время выполнения с настраиваемыми параметрами для обработки расширенных сценариев проверки подлинности.
Дополнительные сведения см. в следующих статьях:
- Защита ASP.NET Core Blazor WebAssembly
- Сценарии обеспечения дополнительной безопасности ASP.NET Core Blazor WebAssembly
Blazor WebAssembly улучшения отладки
Blazor WebAssembly Отладка имеет следующие улучшения:
- Поддержка параметра Just My Code для отображения или скрытия элементов типа, не входящих в пользовательский код.
- Поддержка проверки многомерных массивов.
- Теперь стек вызовов отображает правильное имя асинхронных методов.
- Улучшенная оценка выражений.
- Правильная обработка ключевого слова на производных
new
элементах. - Поддержка атрибутов, связанных с отладчиком, в
System.Diagnostics
.
System.Security.Cryptography
поддержка в WebAssembly
.NET 6 поддерживает семейство хэширования алгоритмов SHA при выполнении в WebAssembly. .NET 7 позволяет использовать более криптографические алгоритмы, используя преимущества SubtleCrypto, когда это возможно, и вернуться к реализации .NET, когда SubtleCrypto не удается использовать. Следующие алгоритмы поддерживаются в WebAssembly в .NET 7:
- SHA1
- SHA256
- SHA384
- SHA512
- HMACSHA1
- HMACSHA256
- HMACSHA384
- HMACSHA512
- AES-CBC
- PBKDF2
- HKDF
Дополнительные сведения см. в статье Разработчики, предназначенные для браузера, могут использовать API веб-шифрования (dotnet/runtime #40074).
Внедрение служб в настраиваемые атрибуты проверки
Теперь можно внедрить службы в настраиваемые атрибуты проверки. Blazor настраивает его ValidationContext
таким образом, чтобы его можно было использовать в качестве поставщика услуг.
Дополнительные сведения см. в разделе ASP.NET Проверка основных Blazor форм.
Input*
компоненты за пределами EditContext
/EditForm
Встроенные входные компоненты теперь поддерживаются за пределами формы в Razor разметке компонента.
Дополнительные сведения см. в разделе ASP.NET Основные Blazor входные компоненты.
Изменения шаблона проекта
Когда .NET 6 был выпущен в прошлом году, разметка _Host
HTML страницы (Pages/_Host.chstml
) была разделена между _Host
страницей и новой _Layout
страницей (Pages/_Layout.chstml
) в шаблоне проекта .NET 6 Blazor Server .
В .NET 7 разметка HTML была перекомбинирована со страницей _Host
в шаблонах проектов.
В шаблоны проектов были внесены Blazor несколько дополнительных изменений. Невозможно перечислить каждое изменение шаблонов в документации. Сведения о переносе приложения в .NET 7 для принятия всех изменений см. в статье "Миграция с ASP.NET Core 6.0 на 7.0".
Экспериментальный QuickGrid
компонент
Новый QuickGrid
компонент предоставляет удобный компонент сетки данных для наиболее распространенных требований, а также в качестве эталонной архитектуры и базовых показателей производительности для всех, кто создает Blazor компоненты сетки данных.
Дополнительные сведения см. в разделе ASP.NET Компонент QuickGrid CoreBlazor.
Демонстрация в реальном времени: QuickGrid для Blazor примера приложения
Усовершенствования виртуализации
Усовершенствования виртуализации в .NET 7:
- Компонент
Virtualize
поддерживает использование самого документа в качестве корня прокрутки в качестве альтернативы применению другого элементаoverflow-y: scroll
. - Если компонент
Virtualize
помещается в элемент, которому требуется определенное имя дочернего тега,SpacerElement
разрешает получить или задать имя тега разделителя в виртуализации.
Дополнительные сведения см. в следующих разделах статьи "Виртуализация ".
MouseEventArgs
Обновления
MovementX
и MovementY
были добавлены MouseEventArgs
в .
Дополнительные сведения см. в статье Обработка событий Blazor в ASP.NET Core.
Новая Blazor страница загрузки
Шаблон Blazor WebAssembly проекта имеет новый пользовательский интерфейс загрузки, показывающий ход загрузки приложения.
Дополнительные сведения см. в статье Запуск ASP.NET Core Blazor.
Улучшена диагностика для проверки подлинности вBlazor WebAssembly
Чтобы диагностировать проблемы с проверкой подлинности в Blazor WebAssembly приложениях, доступна подробная регистрация.
Дополнительные сведения см. в разделе ASP.NET Ведение журнала CoreBlazor.
Взаимодействие JavaScript в WebAssembly
API взаимодействия JavaScript — это новый низкоуровневый механизм использования .NET в приложениях на основе JavaScript[JSImport]
[JSExport]
/.Blazor WebAssembly Благодаря этой новой возможности взаимодействия JavaScript можно вызывать код .NET из JavaScript с помощью среды выполнения .NET WebAssembly и вызывать функции JavaScript из .NET без каких-либо зависимостей от модели компонента пользовательского Blazor интерфейса.
Дополнительные сведения см. по ссылке .
- Взаимодействие JavaScript JSImport/JSExport с ASP.NET Core Blazor: относится только к приложениям Blazor WebAssembly .
- Взаимодействие JavaScript "[JSImport]/[JSExport]" в .NET WebAssembly: относится только к приложениям JavaScript, которые не зависят от модели компонентов пользовательского Blazor интерфейса.
Условная регистрация поставщика состояния проверки подлинности
До выпуска .NET 7 AuthenticationStateProvider
был зарегистрирован в контейнере AddScoped
службы. Это усложняло отладку приложений, так как при предоставлении пользовательской реализации было принудительно выполнено определенное порядок регистрации служб. Из-за внутренних изменений платформы со временем больше не требуется зарегистрировать AuthenticationStateProvider
в AddScoped
.
В коде разработчика внесите следующее изменение в регистрацию службы поставщика состояний проверки подлинности:
- builder.Services.AddScoped<AuthenticationStateProvider, ExternalAuthStateProvider>();
+ builder.Services.TryAddScoped<AuthenticationStateProvider, ExternalAuthStateProvider>();
В предыдущем примере ExternalAuthStateProvider
— это реализация службы разработчика.
Улучшения средств сборки .NET WebAssembly
Новые функции рабочей нагрузки wasm-tools
для .NET 7, которые помогают повысить производительность и обрабатывать исключения:
- Поддержка одной инструкции WebAssembly, поддержка нескольких данных (SIMD) (только с AOT, не поддерживаемой Apple Safari)
- Поддержка обработки исключений WebAssembly
Дополнительные сведения см. в статье ASP.NET Средства сборки Core Blazor WebAssembly и компиляция с заранеей компиляцией (AOT).
Blazor Hybrid
Внешние URL-адреса
Добавлен параметр, позволяющий открывать внешние веб-страницы в браузере.
Дополнительные сведения см. в статье Маршрутизация ASP.NET Core Blazor Hybrid и навигация.
Безопасность
Новые рекомендации доступны для Blazor Hybrid сценариев безопасности. Дополнительные сведения см. в следующих статьях:
- Проверка подлинности и авторизация в Blazor Hybrid ASP.NET Core
- Вопросы обеспечения безопасности в ASP.NET Core Blazor Hybrid
Производительность
По промежуточному слоям кэширования выходных данных
Кэширование выходных данных — это новое ПО промежуточного слоя, которое хранит ответы из веб-приложения и обслуживает их из кэша, а не вычисляет их каждый раз. Кэширование выходных данных отличается от кэширования ответов следующими способами:
- Поведение кэширования настраивается на сервере.
- Записи кэша могут быть программным образом недействительными.
- Блокировка ресурсов снижает риск метки кэша и гром стада.
- Повторная проверка кэша означает, что сервер может возвращать
304 Not Modified
код состояния HTTP вместо кэшированного текста ответа. - Среда хранилища кэша расширяема.
Дополнительные сведения см. в разделе "Обзор кэширования и кэширования выходных данных" по промежуточному слоям.
Улучшения HTTP/3
Этот выпуск:
- Делает HTTP/3 полностью поддерживаемым ASP.NET Core, он больше не экспериментальн.
- Улучшает Kestrelподдержку HTTP/3. Двумя основными областями улучшения являются четность функций с HTTP/1.1 и HTTP/2, а также производительность.
- Обеспечивает полную поддержку UseHttps(ListenOptions, X509Certificate2) http/3. Kestrelпредоставляет дополнительные параметры настройки сертификатов подключения, например перехват в указание имени сервера (SNI).
- Добавляет поддержку HTTP/3 в HTTP.sys и IIS.
В следующем примере показано, как использовать обратный вызов SNI для разрешения параметров TLS:
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
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 =
MyResolveCertForHost(context.ClientHelloInfo.ServerName)
};
return new ValueTask<SslServerAuthenticationOptions>(options);
},
});
});
});
В .NET 7 была проведена важная работа по сокращению выделения HTTP/3. Некоторые из этих улучшений можно увидеть в следующих GitHub PR:
- HTTP/3. Избегайте выделения маркеров отмены на запрос
- HTTP/3. Избегайте выделения ConnectionAbortedException
- HTTP/3: пул ValueTask
Улучшения производительности HTTP/2
.NET 7 представляет значительную переработанную архитектуру того, как Kestrel обрабатывает запросы HTTP/2. В приложениях ASP.NET Core с загруженными подключениями HTTP/2 будет наблюдаться снижение использования ЦП и повышение пропускной способности.
Ранее реализация мультиплексирования HTTP/2 зависела от блокировки, контролирующей то, какой запрос может выполнять запись в базовое подключение TCP. Потокобезопасная очередь заменяет блокировку записи. Теперь вместо того, чтобы потоки конкурировали за использование блокировки записи, запросы ставятся в очередь, и их обрабатывает выделенный потребитель. Ранее ресурсы ЦП были доступны rest приложению.
Одним из мест, где можно заметить эти улучшения, является gRPC, популярная платформа RPC, использующая HTTP/2. Показатели Kestrel + gRPC показывают существенное улучшение:
Изменения были внесены в код написания кода HTTP/2, что повышает производительность при наличии нескольких потоков, пытающихся записывать данные в одном подключении HTTP/2. Теперь мы отправим TLS в пул потоков и более быстро выпускаем блокировку записи, которую другие потоки могут получить для записи своих данных. Сокращение времени ожидания может повысить производительность в случаях, когда для этой блокировки записи возникает конфликт. Тест gRPC с 70 потоками в одном соединении (с TLS) показал улучшение запросов в секунду (RPS) на ~15 % с этим изменением.
Поддержка WebSockets по HTTP/2
.NET 7 представляет webSockets через поддержку HTTP/2 для Kestrelклиента SignalR JavaScript и SignalR с Blazor WebAssembly.
При использовании соединений WebSocket по HTTP/2 доступны новые возможности, в том числе следующие:
- сжатие заголовка;
- мультиплексирование, которое сокращает время и ресурсы, необходимые для выполнения нескольких запросов к серверу.
Эти функции доступны в Kestrel на всех платформах с поддержкой HTTP/2. Согласование версии выполняется в браузерах и Kestrel автоматически, поэтому новые интерфейсы API не требуются.
Дополнительные сведения см. в разделе поддержки Http/2 WebSockets.
Улучшенная производительность Kestrel на компьютерах с большим количеством ядер
Kestrel использует ConcurrentQueue<T> для многих целей. Одна из них — планирование операций ввода-вывода при транспортировке Kestrel на основе сокетов по умолчанию. Секционирование ConcurrentQueue
на основе связанного сокета сокращает состязание и увеличивает пропускную способность на компьютерах с большим количеством ядер ЦП.
Профилирование на компьютерах с большим количеством ядер на .NET 6 продемонстрировало значительный показатель состязания в одном из других экземпляров ConcurrentQueue
Kestrel, в пуле PinnedMemoryPool
, который Kestrel использует для кэширования буферов байтов.
В .NET 7 пул памяти Kestrel секционируется так же, как и его очередь ввода-вывода, что значительно сокращает состязание и увеличивает пропускную способность на компьютерах с большим количеством ядер. На виртуальных машинах ARM64 с 80 ядрами наблюдается повышение числа ответов в секунду (RPS) более чем на 500 % по результатам теста производительности TechEmpower с открытым текстом. На 48 основных виртуальных машинах AMD улучшение почти на 100 % в нашем тесте JSON HTTPS.
Событие ServerReady
для измерения времени запуска
Приложения, использующие EventSource, могут измерять время запуска, чтобы определить и оптимизировать его производительность. Новое событие ServerReady
в Microsoft.AspNetCore.Hosting представляет точку, в которой сервер готов отвечать на запросы.
Сервер
Событие New ServerReady для измерения времени запуска
Событие ServerReady
было добавлено для измерения времени запуска приложений ASP.NET Core.
IIS
Теневое копирование в IIS
Теневое копирование сборок приложений в модуль ASP.NET Core (ANCM) для IIS может быть удобнее для пользователя, чем остановка приложения путем развертывания автономного файла приложения.
Дополнительные сведения см. в разделе "Теневое копирование" в службах IIS.
Прочие условия
Kestrel улучшения полной цепочки сертификатов
HttpsConnectionAdapterOptions имеет новое свойство ServerCertificateChain типа X509Certificate2Collection, что упрощает проверку цепочек сертификатов, позволяя выполнять полную цепочку, включая промежуточные сертификаты. Дополнительные сведения см. в dotnet/aspnetcore#21513 .
dotnet watch
Улучшенные выходные данные консоли для dotnet watch
Выходные данные консоли из dotnet watch были улучшены, чтобы соответствовать ведению журнала в ASP.NET Core, и дополнены 😮эмодзи😍.
Вот пример того, как выглядят новые выходные данные:
Дополнительные сведения см. в этом запросе на вытягивание на GitHub.
Настройка dotnet watch для перезапуска при грубых изменениях
Грубые изменения — это изменения, которые не подлежат горячей перезагрузке. Чтобы настроить dotnet watch для перезапуска без запроса в случае грубых изменений, задайте для переменной среды DOTNET_WATCH_RESTART_ON_RUDE_EDIT
значение true
.
Темный режим страницы исключений для разработчиков
Поддержка темного режима была добавлена на страницу исключений для разработчиков благодаря участию Патрика Вестерхоффа (Patrick Westerhoff). Чтобы протестировать темный режим в браузере, на странице инструментов разработчика установите темный режим. Например, в Firefox:
В Chrome:
Параметр шаблона проекта для использования метода Program.Main вместо инструкций верхнего уровня
В шаблонах .NET 7 можно не использовать инструкции верхнего уровня и не создавать namespace
и метод Main
, объявенный в классе Program
.
С помощью .NET CLI задайте параметр --use-program-main
:
dotnet new web --use-program-main
В Visual Studio установите флажок Не использовать инструкции верхнего уровня при создании проекта:
Обновленные шаблоны Angular и React
Шаблон проекта Angular обновлен до Angular 14. Шаблон проекта React обновлен до React 18.2.
Управление веб-токенами JSON в разработке с помощью dotnet user-jwts
Новое dotnet user-jwts
средство командной строки может создавать локальные веб-маркеры JSON и управлять ими. Дополнительные сведения см. в разделе "Управление веб-токенами JSON в разработке с помощью dotnet user-jwts".
Поддержка дополнительных заголовков запросов в W3CLogger
Теперь вы можете указывать дополнительные заголовки запросов для регистрации при использовании средства ведения журнала W3C. Для этого вызовите AdditionalRequestHeaders()
для класса W3CLoggerOptions:
services.AddW3CLogging(logging =>
{
logging.AdditionalRequestHeaders.Add("x-forwarded-for");
logging.AdditionalRequestHeaders.Add("x-client-ssl-protocol");
});
Дополнительные сведения см. в параметрах W3CLogger.
Распаковка запросов
Новое ПО промежуточного слоя для распаковки запросов предоставляет такие преимущества:
- позволяет конечным точкам API принимать запросы со сжатым содержимым;
- использует заголовок HTTP
Content-Encoding
, чтобы автоматически обнаруживать и распаковывать запросы, содержащие сжатое содержимое; - устраняет необходимость писать код для обработки сжатых запросов.
Дополнительные сведения см. в разделе ПО промежуточного слоя для распаковки запросов.
ASP.NET Core