Форум программистов, компьютерный форум, киберфорум
C#: ASP.NET Core
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,590
Записей в блоге: 2
.NET 8

Nullable и Actions параметры. Что настроено у вас?

05.01.2025, 22:46. Показов 990. Ответов 4

Студворк — интернет-сервис помощи студентам
Провожу глобальный рефакторинг в проекте который был мигрирован с AspNet5 на AspNetCore. И дошли руки до того чтобы активировать режим NullableEnable и навсегда перестать бояться NRE (ну вы поняли).
Все проекты-библиотеки-сервисы обновил, а когда дело дошло до веб-приложений, то тут возникла резко одна неприятная проблема и не понятная ситуация.

Если включить Nullable:Enable то большинство экшенов перестанут работать, так как там параметры стали все по умолчанию требуемыми и мы получаем 404 вместо старого поведения: входим в экшен и видим что параметр имеет значение null. Это разумеется относится в первую очередь к String и разным объектам.
Тот же LogOn, который по умолчанию имеет примерно такую сигнатуру
Code
1
IActionResult LogOn(String redirectUrl=null)
перестал работать, так как и не решил наделить параметр возможностью быть нуллабле, так и анализатор что-то решил мне не намекать на то что тут стоит "?" поставить.

И вот вопрос. Что-то я не в видео, не в чужих примерах никогда не видел нуллабле параметры.
- никто не использует такой режим?
- у всех настолько чёткая схема обработки?
- или всё-таки я не видел, и у большинства действительно все действия натыканы "?" нуллификаторами?

Уточню ситуацию. Например, мы иногда позволяем придти объекту пустому. Потому что
- или есть ещё другие на которых ветка логики изменится
- или нужно самому вернуть ошибку с нужным текстом (а не какой-то центральный обработчик который дефолтный текст пихнёт)
- или... хочу больше контроля.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.01.2025, 22:46
Ответы с готовыми решениями:

IE5 при первой загрузке говорит, что у вас не настроено подключение к Internet. И типа спрашивает повторить?. Повторяю. Подключается.
Всем привет. На Win2000Server c IIS5.0 такая штука. IE5 при первой загрузке говорит, что у вас не настроено подключение к Internet....

Это теперь стандарт - <Nullable>enable</Nullable>?
При создании нового проекта в VS2022 на базе Net6 в файле проекта по умолчанию стоит &lt;Nullable&gt;enable&lt;/Nullable&gt; Это теперь...

Что не так настроено?
Есть сервер на нем стоит Windows Server 2003 есть внешний ip адрес. Инет подается через vpn соединение. На серваке интернет работает,...

4
1338 / 918 / 264
Регистрация: 08.08.2014
Сообщений: 2,759
06.01.2025, 13:27
Если параметр '[FromRoute]', то он же в принциипе не может быть 'nullable', т.к. если параметра нет в маршруте, то это другой маршрут и он либо сопоставляется с другим методом, либо 404. Если же такой параметр есть в маршруте, то он уже не 'null'.

Если же параметр '[FromQuery]' или '[FromBody]', то всега описываю все свойства как 'nullable', в т.ч. чтобы не было неоднозначности в интерпретации значений, когда в DTO есть свойство 'int Status { get; set; }', в исходном JSON (из тела запроса) свойства 'Status' вообще нет, и свойство 'Status' в десериализованном DTO получает значение 'default(int)', ну т.е. ноль. И в валидаторе нет никакой возможности понять, это ноль, потому что клиент ноль прислал, или ноль, потому что клиент вообще забыл это свойство отправить. Если же свойство DTO будет 'int?', то значение '0' будет означать, что там реально ноль, т.е. что клиент именно ноль прислал. При этом 'int?' вполне может быть и обязательным свойством с точки зрения бизнес-правил метода.

В некоторых сценариях дополнительно выполняю ручной парсинг исходного запроса, чтобы понять, какие свойства клиент реально прислал.
1
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,590
Записей в блоге: 2
06.01.2025, 15:34  [ТС]
Ну, это идеальная схема, как и рекомендуют.
У тебя не было миграций старого проекта? Получается что для нового кода ты сразу придерживаешься правил. Верно?

Цитата Сообщение от kotelok Посмотреть сообщение
Если же параметр '[FromQuery]' или '[FromBody]', то всега описываю все свойства как 'nullable', в т.ч. чтобы не было неоднозначности в интерпретации значений
Свойства модели - да. А параметры прямо в экшене? Например,
C#
1
2
3
4
5
6
IActionResult Post(string name)
{
   if (name == null){
      return BadRequest();
   }
}
Раньше было так. Сейчас то что, придётся ставить везде нуллификатор? У тебя как с этим обстоит?
Потому что если не поставить, то мы даже не попадаем в метод, получаем 404.

Я ищу какой-то рабочий вариант в котором "и овцы сыты и волки целы". Проект большой и обновить все экшены и отредактировать модели сложно и трудоёмко, так как каждую модель нужно идеально знать и быть уверенным ожидаются ли нуллабле значение или нет. Это решается глубоким анализом кода по чтению этой модели. Например, где то в итоге написано "if name != null...." то можно уже почти уверенно сказать что это ожидалось и предусмотрено. Но если у всех моделей у string натыкать нуллификаторы, то скорее всего я получу огромное количество работы по разгребанию варнингов.

Кстати, для моделей нашлась настройка:
C#
1
2
3
4
services.AddMvc(opt =>
{
    opt.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;
});
которая воспроизводит старое поведение. НО только для свойств модели. Но не для параметров экшена. И не для всех свойств модели (как оказалось).
0
1338 / 918 / 264
Регистрация: 08.08.2014
Сообщений: 2,759
06.01.2025, 19:39
Цитата Сообщение от HF Посмотреть сообщение
Свойства модели - да. А параметры прямо в экшене?
Если параметры передаются как часть маршрута, то я такой вариант ни разу не использовал, т.к. воспринимаю маршрут именно как путь к некоему API-ресурсу, и там максимум что-то вроде такого может быть:
Code
1
2
3
4
[GET] api/items/{id}
[GET] api/items/?<filters, orderby, pagination>
[PATCH] api/items/{id} { DTO }
[PATCH] api/items/{id}/someAction
Если же параметры - это именно query-параметры, то они на распознавание маршрута никак не влияют, все могут быть 'nullable', как и свойства DTO (в который тело десериализуется). Более того, сейчась ведь можно даже так делать:
C#
1
public void SomeAction([FromQuery] QueryDto queryDto)
И оно автоматом создаст экземпляр 'QueryDto' и разложит в его свойства те query-параметры, которые удалось найти в запросе (ну или оставит все свойства в null-значении, если клиент не передал ни одного параметра). И там даже коллекции поддерживаются.

Цитата Сообщение от HF Посмотреть сообщение
Проект большой и обновить все экшены и отредактировать модели сложно и трудоёмко
Так а нельзя, именно для наследных проектов, просто не трогать параметры и оставить всё как есть? Код рабочий ведь, и продолжит работать, а варнинги можно просто подавить либо через параметры проекта, либо локально для каждого метода.

P.S.: в последнем проекте я вообще отказался от ручного написания контроллеров, генерирую их в рантайме через анализ сборок с сервисами.

Добавлено через 1 час 20 минут
Цитата Сообщение от HF Посмотреть сообщение
и навсегда перестать бояться NRE
А JSON-сериализаторы уже научились корректно обрабатывать ситуации, когда в DTO есть НЕ-nullable свойство, а в десериализуемом JSON этого свойства нет?

А то у меня одно клиентское приложение на NET-6, там эта проблема имеет место быть, ну т.е. после десериализации вполне можно получить null-значение в НЕ-nullable свойстве. В итоге, согласно анализатору, всё ок, NRE быть не может, а в рантайме оно всё же иногда происходит.
0
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,590
Записей в блоге: 2
07.01.2025, 00:01  [ТС]
Цитата Сообщение от kotelok Посмотреть сообщение
Если параметры передаются как часть маршрута, то я такой вариант ни разу не использовал, т.к. воспринимаю маршрут именно как путь к некоему API-ресурсу, и там максимум что-то вроде такого может быть
Да, всё так и есть, тут всё чётко. Тут мы или 404 получим или всё-таки попадаем куда надо и переходим к обсуждению уже п.2.

Цитата Сообщение от kotelok Посмотреть сообщение
И оно автоматом создаст экземпляр 'QueryDto' и разложит в его свойства те query-параметры, которые удалось найти в запросе (ну или оставит все свойства в null-значении, если клиент не передал ни одного параметра). И там даже коллекции поддерживаются.
Да вот тут и начинаются сложности. Это сразу частично отвечает на твой последний вопрос "...уже научились корректно...?"
Сложность именно в том какие свойства в модели. Если там набор свойств такой, что десериализатор не смог собрать такую модель, то ты получишь так же можешь получить null вместо объекта (в твоём примере QueryDto).
И тогда то что я спрашивал выше - тут только ставить "?" нулификатор. Потому что при такой ситуации, контроллер бросает ошибки запросов - может 404, 400, даже 417 был. В экшен не попадаем.

Вот например как выглядит банальная форма логина - метод Get просто возвращает модель где есть необязательные string. Но так как сейчас он их все считает обязательными, то даже после Get я уже получаю форму с красными полями валидации. Ну а Post вообще не работает.

Цитата Сообщение от kotelok Посмотреть сообщение
Так а нельзя, именно для наследных проектов, просто не трогать параметры и оставить всё как есть? Код рабочий ведь, и продолжит работать, а варнинги можно просто подавить либо через параметры проекта, либо локально для каждого метода.
Я так и делаю. Все проекты уже исправлены под NullableEnable. А у веб-приложений стоит NullableWarnings и исправлены критические (или явные) ситуации.
Конечно можно оставить. Скорее всего так и будет, так как я пока не придумал хорошего плана миграции.
"Но осадочек то остался". Я же знаю что это не закончено и буду пытаться. По мере "трогания" кода что-то переписывать.

Цитата Сообщение от kotelok Посмотреть сообщение
А JSON-сериализаторы уже научились корректно обрабатывать ситуации, когда в DTO есть НЕ-nullable свойство, а в десериализуемом JSON этого свойства нет?
А то у меня одно клиентское приложение на NET-6, там эта проблема имеет место быть, ну т.е. после десериализации вполне можно получить null-значение в НЕ-nullable свойстве. В итоге, согласно анализатору, всё ок, NRE быть не может, а в рантайме оно всё же иногда происходит.
Возможно знаю о чём ты говоришь, а возможно и нет. Нужен пример.
Но если это то что я думаю, то проблем у меня нет ни с чем. Просто надо правильно организовать модель и атрибуты, чтобы управлять результатом.
В вашем случае возможна такая ситуация:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#nullable enable
void Main()
{
    string json11 = "{ \"Id\": 1, \"Name\": \"Test\" }";
    JsonSerializer.Deserialize(json11, typeof(MyClass)).Dump();
 
    string json12 = "{ \"Id\": 1 }";
    JsonSerializer.Deserialize(json12, typeof(MyClass)).Dump();
 
    string json21 = "{ \"Id\": 1 }";
    JsonSerializer.Deserialize(json21, typeof(MyClass2)).Dump();
}
 
public class MyClass
{
    public int Id { get; set; } 
    public string Name { get; set; }
}
 
public class MyClass2
{
    public int Id { get; set; }
 
    [JsonRequired]
    public string Name { get; set; }
}
Результаты:
1) идеальный
2) Name = null
3) JsonException

Ну и смотря где используется модель.
Для второго случая, я ставлю атрибут Required и тогда ModelState будет невалидный с соответствующими удобствами.

Добавлено через 3 минуты
Советчики вот такую инструкцию рекомендовали для любой ситуации:
* C# 8.0 nullable references and serialization

По умолчанию для ModelState не сильно подходит.
Это скорее для десериализации, чтобы иметь чёткую модель уже на первой стадии создания объекта.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
07.01.2025, 00:01
Помогаю со студенческими работами здесь

я что-то забыл?! Shared Actions
я не уверен, по поводу влияния внешних факторов (звёзды, погода в африке...) или в памяти стали стираться подробности данной фичи... у...

Как проверить, что тип T является типом Nullable<T1>?
Как проверить, что тип T является типом Nullable&lt;T1&gt;, где T1 неизвестный тип?

Что оптимальнее - nullable bool или enum на три значения
Изначально нужна была переменная, чтобы хранить 2 значения. Но потом понадобилось добавить еще третье - дефолтное значение, из-за чего я...

Что за встроенный тип Nullable и как его использовать, чтоб не подчёркивало красным?
Какие настройки нужно выставить в tsconfig.json? Спасибо

Как должна быть организована сеть офиса? Что должно быть настроено обязательно, а чего быть не должно?
Добрый день. Сразу оговорюсь, что я инженер-строитель и настройкой сети занимаюсь только потому, что больше некому. Поэтому некоторые,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru