Подтвердить что ты не робот

Исключение 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
4b9b3361

Ответ 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."/>