Исключение ASP.NET MVC Html.RadioButton
У меня есть простой список переключателей на моей странице, который я визуализирую со следующим:
<label for="gender">Gender</label>
<%= Html.RadioButton("gender", 1) %> Male
<%= Html.RadioButton("gender", 2) %> Female
<%= Html.ValidationMessage("gender") %>
Обратите внимание, что когда пользователь изначально видит этот ввод, ни одна из них не выбрана.
Валидация заключается в том, чтобы заставить их выбирать и не принимать значение по умолчанию.
Следовательно, эти два переключателя привязаны к объекту с нулевым значением int в моей модели, объявленной как:
public int? gender { get; set; }
Поэтому, если они не выбирают кнопку и не представляют страницу, свойство gender будет null, что указывает на то, что они не выбрали. Следующее подтверждение вызывается контроллером во время публикации:
if (!gender.HasValue)
ModelState.AddModelError("gender", "gender required");
Но если проверка не удалась (они не выбрали), то во время фазы рендеринга среда MVC создает следующее исключение:
System.NullReferenceException was unhandled by user code
Message="Object reference not set to an instance of an object."
В поисках решения этой проблемы я заметил, что некоторые из них столкнулись с этой проблемой.
Я использую ASP.NET MVC 1.0. Я нашел место в коде, где эта ошибка генерируется с помощью .NET Reflector.
Вопрос в том, как правильно сделать эту работу?
EDIT: добавить stacktrace:
System.NullReferenceException was unhandled by user code
Message="Object reference not set to an instance of an object."
Source="System.Web.Mvc"
StackTrace:
at System.Web.Mvc.HtmlHelper.GetModelStateValue(String key, Type destinationType)
at System.Web.Mvc.Html.InputExtensions.InputHelper(HtmlHelper htmlHelper, InputType inputType, String name, Object value, Boolean useViewData, Boolean isChecked, Boolean setId, Boolean isExplicitValue, IDictionary`2 htmlAttributes)
at System.Web.Mvc.Html.InputExtensions.RadioButton(HtmlHelper htmlHelper, String name, Object value, Boolean isChecked, IDictionary`2 htmlAttributes)
at System.Web.Mvc.Html.InputExtensions.RadioButton(HtmlHelper htmlHelper, String name, Object value, IDictionary`2 htmlAttributes)
at System.Web.Mvc.Html.InputExtensions.RadioButton(HtmlHelper htmlHelper, String name, Object value)
at ASP.views_vbs_register_aspx.__RenderregisterContent(HtmlTextWriter __w, Control parameterContainer) in c:\Users\David\Documents\BellevueProject\Bellevue\BellevueTeachers\Forms\Views\VBS\Register.aspx:line 42
Ответы
Ответ 1
Я просто попробовал что-то, что делает эту работу.
Проблема не возникает, если я не делаю шаг проверки, но, конечно, мне нужна проверка.
Это дало мне ключ к решению.
Метод ValidationMessage HtmlHelper принимает строковый аргумент, который является именем проверяемого свойства или объекта модели.
Я просто изменил это имя на "gender2" следующим образом:
<label for="gender">Gender</label>
<%= Html.RadioButton("gender", 1) %> Male
<%= Html.RadioButton("gender", 2) %> Female
<%= Html.ValidationMessage("gender2") %>
И я изменил код проверки, чтобы ссылаться на это новое имя (хотя это свойство не существует, оно все еще работает):
if (!gender.HasValue)
ModelState.AddModelError("gender2", "gender required");
Это работает по желанию.
Я бы подумал, что другой должен сработать, но это простой обходной путь, и я документирую это здесь.
EDIT:
Кстати, я попытался изменить свойство gender на строку, а не на nullable int, и возникает точная проблема.
Работа по-прежнему, по-видимому, связана с использованием другого имени ключа для Message Validation.
Ответ 2
Это очень похоже, если не соответствует проблеме флажка: Хелперный метод Html.Checkbox() генерирует скрытое поле с ложным значением. Если это поле отсутствовало, браузер не будет отправлять какие-либо данные для необработанных ящиков.
Однако радиобъект должен иметь значение, а возможные значения могут быть более одного. В этом случае не так просто обрабатывать случай, не относящийся к выбору, который, я думаю, является причиной, по которой это не так.
Обходной путь для меня заключался в том, чтобы добавить скрытое поле следующим образом:
<%= Html.RadioButton("gender", 1) %> Male
<%= Html.RadioButton("gender", 2) %> Female
<%= Html.Hidden("gender", null) %>
Ответ 3
Возможно, вы захотите попробовать сменить пол на строку (M/F) вместо int и посмотреть, работает ли это.
Если вы абсолютно должны иметь его как int, вы всегда можете перевести его на задний план.
private int? gender { get; set; }
public string displayGender
{
get
{
return this.gender.HasValue
? (this.gender.Value == 1 ? "M" : "F" )
: null;
}
set
{
this.gender = null;
if (value == "M")
this.gender = 1;
else if (value == "F")
this.gender = 2;
}
}
<label for="gender">Gender</label>
<%= Html.RadioButton("displayGender", "M") %> Male
<%= Html.RadioButton("displayGender", "F") %> Female
<%= Html.ValidationMessage("displayGender") %>
Основываясь на своем комментарии, вы можете добавить:
<%= Html.RadioButton("displayGender",
string.Empty,
true, // this is the default
new { @style = "display: none;" } ) %>
Это обеспечит отправку displayGender назад (всегда будет выбранная радиостанция), и я думаю, что значение будет string.Empty вместо нулевой ссылки. Если это сработает, вы можете попробовать вернуться к нулевому int.
Ответ 4
Попробуйте добавить следующую строку кода после ModelState.AddModelError()
:
ModelState.SetModelValue("gender", ValueProvider["gender"]);
Ответ 5
Если вы хотите подключиться к проверке на стороне клиента. Пропустите html-помощник и вручную напишите радиостанции, предоставив им атрибуты для данных-val и data-val-required. Вот так.
<input type="radio" name="displayGender" id="displayGender" value="1" data-val="true" data-val-required ="The gender field is required."/>
<input type="radio" name="displayGender" id="displayGender" value="2" data-val="true" data-val-required ="The gender field is required."/>