Почему мы не можем установить значение null для параметра элемента select с типом nullable?

#c# #asp.net #asp.net-mvc

#c# #asp.net #asp.net-mvc

Вопрос:

Предположим, у нас есть модель со свойством WillMarry bool? типа. Мы можем неявно вызывать все следующие действия без каких-либо проблем.

  • obj.WillMarry=null;
  • obj.WillMarry=false;
  • obj.WillMarry=true;

Теперь рассмотрим следующее ASP.NET Страница просмотра MVC.

 <select asp-for="WillMarry">
    <option value="">Choose an option</option>
    <option value="true">Yes, I will get married</option>
    <option value="false">No, I will not get married</option>
</select>
 

Привязка модели может заполнять и value="true" то , и другое , и value="false" для параметра WillMarry with ModelState.IsValid установлено значение true . Однако он будет установлен ModelState.IsValid на false , если я использую value="null" вместо value="" .

Вопрос

Если мы можем установить obj.WillMarry=null неявно, почему привязка модели не может быть установлена WillMarry на null via value="null" и без установки ModelState.IsValid на false ?

Редактировать

Вероятно, мне придется перефразировать свой вопрос следующим образом.

  • Мы можем установить obj.WillMarry=false неявно, и связыватель модели также может преобразовать value="false" в false .
  • Мы можем установить obj.WillMarry=true неявно, и связыватель модели также может преобразовать value="true" в true .
  • Мы можем установить obj.WillMarry=null неявно, ОДНАКО связыватель модели не может преобразовать value="null" (вместо value="" ) в null .

Почему существует такое странное поведение в привязке модели только для null ?

Ответ №1:

Когда вы отправляете форму, вы отправляете имя / значение пары его успешных элементов управления в запросе. Если вы выберете первый вариант с value="null" value="" не с), он отправит WillMarry: null .

Все, что отправляется в запросе, — это просто текст (понятия типов не существует), и ответственность за DefaultModelBinder преобразование значений в тип свойства лежит на нем. В вашем случае DefaultModelBinder находит соответствующее имя свойства в вашей модели (свойство, которое есть public bool? WillMarry { get; set; } ) и пытается установить его путем преобразования текста "null" в a boolean , который завершается с ошибкой и ModelState становится недействительным.

Для представления a null отправляемое значение должно быть пустой строкой.

Комментарии:

1. Учитывая, что мы можем делать obj.WillMarry=null; неявно, почему связующее значение модели не может "null" быть преобразовано в логическое значение с нулевым значением?

2. Потому что текст «null» не совпадает с null . Существует разница между bool? WillMarry = null; и bool? WillMarry = "null"; . Изображение у вас есть свойство, которое является typeof string, и вы разместили значение «null» — ожидаете ли вы DefaultModelBinder , что для свойства будет установлено null значение или значение «null» 🙂

3. С тем же мышлением, obj.WillMarry=false это не то же самое, что WillMarry="false" но model binder может сделать это без каких-либо проблем, верно?

4. Потому DefaultModelBinder что используются преобразователи значений, а «false» преобразуется в false . Я не могу использовать преобразователь значений для преобразования «null» в null из-за примера, который я использовал выше. Если вы хотите изучить исходный код, вы можете найти его здесь

5. связующее звено модели было построено таким образом, чтобы оно могло преобразовывать «» в null для обнуляемого bool, что имеет смысл. преобразование «null» в null , возможно, имело бы смысл для c #, но рассмотрим, например, тот же код, написанный на VB.Net . Должен ли код преобразовывать «null», «Nothing» и все, что используется как null в любом сетевом языке, в null ? Я согласен с реализацией, которую они сделали для DefaultModelBinder

Ответ №2:

После вашей правки я перепечатываю свой комментарий в качестве ответа:

связующее звено модели было построено таким образом, чтобы оно могло преобразовывать «» в null для обнуляемого bool, что имеет смысл.

Преобразование «null» в null , возможно, имело бы смысл для c #, но рассмотрим, например, тот же код, написанный на VB.Net .

Должен ли код преобразовывать «null», «Nothing» и все, что используется как null в любом сетевом языке, в null ?

Я согласен с реализацией, которую они сделали для DefaultModelBinder

Комментарии:

1. Является ли Razor механизмом просмотра, зависящим от конкретного языка? Одна страница просмотра не может использовать более одного языка, не так ли? Если да, то для программиста на c # value="null" имеет смысл и для vb.net программист value="nothing" имеет смысл.

2. @SingleFighter Код DefaultModelBinder не зависит от языка, с которого вызывается. Он ведет себя точно так же, если он вызывается анализатором Razor, кодом c #, кодом vb и т. Д., Разработчики сети решили разрешить преобразование из «» в null и не разрешать преобразование из «null», «Nothing» или чего-либо еще в null. Для меня это был правильный выбор.