Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1416. #ЧтоНовенького Новые Возможности MVC в .NET 7. Часть 3 В этой серии рассмотрим некоторые нововведения в ASP.NET Core в .NET 7. Часть 1 Часть 2 3. Использование nullable-аннотаций С каждым выпуском .NET поддержка ссылочных обнуляемых типов становится немного лучше. Для ASP.NET Core в .NET 7 она была добавлена в нескольких местах: 1) Обнуляемое тело запроса В .NET 6 при привязке к телу запроса (независимо от того, используется ли явно [FromBody]), попытка привязки к запросу с пустым телом (где Content-Length == 0) завершится ошибкой "A non-empty request body is required." (Требуется непустое тело запроса). Вы можете обойти это глобально в .NET 6 и разрешить null для параметра, настроив свойство MvcOptions.AllowEmptyInputInBodyModelBinding:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<MvcOptions>(opts =>
{
  opts.AllowEmptyInputInBodyModelBinding = true;
});

Другой вариант - включить его отдельно для каждого метода действия, добавив явный атрибут [FromBody] и установив EmptyBodyBehavior, например:
public IActionResult Post(
 [FromBody(EmptyBodyBehavior=EmptyBodyBehavior.Allow)] 
 MyBody? body)
{
  // body будет null при пустом теле
}
Это работает, но это слишком длинно и уродливо… В .NET 7 всё становится намного проще. Вы можете полагаться на nullable-аннотации. Обнуляемый параметр подразумевает EmptyBodyBehavior.Allow, а необнуляемый - EmptyBodyBehavior.Disallow:
public IActionResult Post(MyBody? body)
{
  // body будет null при пустом теле
}
    
public IActionResult Post(MyBody body)
{
  // При пустом теле будет ошибка 400 
}

2) Определение необязательности сервиса В .NET 6, если вы не зарегистрировали тип сервиса в контейнере внедрения зависимостей, то, даже если декорированный атрибутом [FromService] параметр помечен как обнуляемый, попытка вызова конечной точки API приводит к ошибке: InvalidOperationException: No service for type 'SomeService' has been registered (Сервис типа 'SomeService' не был зарегистрирован) В .NET 7 обнуляемый параметр с атрибутом [FromServices] будет null, если он недоступен в DI:
public IEnumerable<MyClass> Get(
 [FromServices] SomeService? service)
{ … }

Вам может быть интересно, что произойдёт, если вы попытаетесь привязать обнуляемый сервис, который не зарегистрирован в DI, используя автоматическое определение сервиса, описанное в части 2? Ответ: скорее всего, не то, чего вы хотите. Если тип параметра (SomeService выше) не зарегистрирован в DI, он не будет рассматриваться как сервис, он будет рассматриваться как любой другой сложный тип. Это означает, что MVC попытается привязать его свойства к любым доступным параметрам: телу запроса, строке запроса, заголовкам и т.п. Источник: https://andrewlock.net/5-new-mvc-features-in-dotnet-7/