ASP.NET MVC Html.RadioButton Exception - PullRequest
       5

ASP.NET MVC Html.RadioButton Exception

16 голосов
/ 06 апреля 2009

У меня есть простой список переключателей на моей странице, который я отображаю со следующим:

<label for="gender">Gender</label>
<%= Html.RadioButton("gender", 1) %> Male
<%= Html.RadioButton("gender", 2) %> Female
<%= Html.ValidationMessage("gender") %>

Обратите внимание, что когда пользователь изначально видит этот вход, ни одна кнопка не выбирается. Проверка здесь, чтобы заставить их выбирать и не принимать значение по умолчанию. Следовательно, эти две переключатели связаны со свойством типа null в моей модели, объявленной как:

public int? gender { get; set; }

Таким образом, если они не выбирают кнопку и не отправляют страницу, свойство пола будет иметь нулевое значение, что означает, что они не выбрали. Следующая проверка вызывается контроллером во время публикации:

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.

Вопрос в том, как заставить это работать правильно?

РЕДАКТИРОВАТЬ: добавить трассировку стека:

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

Ответы [ 5 ]

11 голосов
/ 06 апреля 2009

Я только что попробовал что-то, что делает эту работу. Проблема не возникает, если я не делаю шаг проверки, но, конечно, мне нужна проверка. Это дало мне ключ к решению.

Метод ValidationMessage HtmlHelper принимает строковый аргумент, который является именем проверяемого объекта свойства или модели. Я просто изменил это имя на «пол2» следующим образом:

<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: Кстати, я попытался изменить свойство пола на строку вместо обнуляемого int, и та же самая проблема возникает.

Обходное решение по-прежнему заключается в использовании другого имени ключа для сообщения проверки.

7 голосов
/ 05 мая 2009

Это очень похоже, если не равно проблеме с флажком: вспомогательный метод Html.Checkbox () создает скрытое поле с ложным значением. Если это поле отсутствует, браузер не будет отправлять данные для не отмеченных ящиков.

Однако предполагается, что радиопереключатель имеет значение, а возможные значения могут быть больше одного. В этом случае не так легко справиться с делом без выбора, что, я думаю, является причиной того, что это не так.

Обходной путь для меня заключался в добавлении скрытого поля следующим образом:

<%= Html.RadioButton("gender", 1) %> Male
<%= Html.RadioButton("gender", 2) %> Female
<%= Html.Hidden("gender", null) %>
1 голос
/ 01 августа 2013

Если вы хотите подключиться к клиентской проверке. Пропустите html helper и напишите свои радиостанции вручную, предоставив им атрибуты для data-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."/>
1 голос
/ 22 апреля 2009

Попробуйте добавить следующую строку кода после ModelState.AddModelError():

ModelState.SetModelValue("gender", ValueProvider["gender"]);
1 голос
/ 06 апреля 2009

Вы можете попробовать изменить пол на строку (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 вместо пустой ссылки. Если это работает, вы можете попробовать вернуться к nullable int.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...