TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.76K subscribers
Post #1746 1.25K
День 1414. #ЧтоНовенького
Новые Возможности MVC в .NET 7. Часть 1
В этой серии рассмотрим некоторые нововведения в ASP.NET Core в .NET 7.

1. IParseable/TryParse для привязки примитивных типов
MVC использует подход «поставщика привязки». Можно привязать параметры методов действий к значениям формы, строки запроса, заголовкам и т.п. По умолчанию MVC связывает некоторые простые типы или любые типы, имеющие TypeConverter из строки. Всё остальное рассматривается как сложный тип, т.е. либо привязывается к телу запроса, либо привязывается не сам тип, а каждое из отдельных свойств типа. Допустим, у нас есть тип:
public class Range
{
public int From { get; set; }
public int To { get; set; }
}
и привязка его в методе действия контроллера:
public class MyController : ControllerBase
{
public IEnumerable<MyClass> Get(Range days)
{ … }
}
В .NET 6 вам нужно либо написать TypeConverter для Range, либо привязать свойства From и To:
/MyController?from=1&to=3

В .NET 7 есть другой вариант. Можно реализовать интерфейс IParseable<T> и создать объект Range из любой строки. Например, мы хотим иметь такой URL:
/MyController/1-3

Формально реализовывать IParseable<T> не нужно, достаточно реализовать метод TryParse(). Пример реализации ниже. Детали не особенно важны, и здесь не учитывается множество пограничных случаев:
public readonly struct Range : IParsable<Range>
{
public int From { get; }
public int To { get; }

public Range(int from, int to)
{
From = from;
To = to;
}

public static bool TryParse(
string? value,
IFormatProvider? provider,
out Range result)
{
if (value != null)
{
var sep = value.IndexOf('-');
if (sep > 0 && sep < value.Length - 1)
{
var fromSpan = value.AsSpan().Slice(0, sep);
var toSpan = value.AsSpan(sep + 1);

if (int.TryParse(fromSpan,
out var from)
&& int.TryParse(toSpan,
out var to))
{
result = new Range(from, to);
return true;
}
}
}

result = default;
return false;
}

public static Range Parse(
string value,
IFormatProvider? provider)
{
if (!TryParse(value, provider, out var result))
throw new ArgumentException();

return result;
}
}

Затем можно просто добавить атрибут к методу контроллера:
[HttpGet("{days}")]
public IEnumerable<MyClass> Get(Range days)
{ … }

Проще ли реализовать IParseable<T>, чем написать свой связыватель модели? Вероятно. Проще, чем свой TypeConverter? Возможно. Однако при этом подходе вы можете использовать одни и те же типы в минимальных API и в контроллерах. Это должно упростить переход от минимальных API к контроллерам (и наоборот).

Если же вы хотите отключить эту функцию, удалите TryParseModelBinderProvider из MvcOptions:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<MvcOptions>(opts => {
opts.ModelBinderProviders
.RemoveType<TryParseModelBinderProvider>();
});

Источник: https://andrewlock.net/5-new-mvc-features-in-dotnet-7/
  • 👍 8
More from @netdeveloperdiary
  1. Oct 13, 2026День 2813. #ЗаметкиНаПолях #Async Ещё Раз Про Async/Await в C#. Часть 1 1. Почему существу…
  2. Oct 12, 2026День 2812. #Карьера #AI Как Разработчикам Оставаться Полезными, Когда Код Пишет ИИ? По мер…
  3. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  4. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  5. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  6. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →