2009-04-06 8 views
16

Je Haver une liste simple bouton radio sur ma page que je rends à ce qui suit à mon avis:ASP.NET MVC Html.RadioButton Exception

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

Notez que lorsque l'utilisateur voit d'abord cette entrée, ni bouton est sélectionné. La validation est là pour les forcer à choisir et à ne pas accepter un défaut. Par conséquent, ces deux boutons radio sont liés à une propriété nullable int dans mon modèle déclaré que:

public int? gender { get; set; } 

Donc, s'ils ne choisissent pas un bouton, et soumettre la page, la propriété de genre sera indiquant nul qu'ils n'a pas sélectionné. La validation suivante est appelée par le contrôleur au cours de la poste:

if (!gender.HasValue) 
    ModelState.AddModelError("gender", "gender required"); 

Mais, si la validation échoue (ils n'ont pas choisi), puis lors de la phase de rendu, l'exception suivante est lancée par le framework MVC:

System.NullReferenceException was unhandled by user code 
    Message="Object reference not set to an instance of an object." 

Dans la recherche d'une solution à ce problème, j'ai noté que plusieurs avaient ce problème. J'utilise ASP.NET MVC 1.0. J'ai trouvé l'endroit dans le code où cette erreur est lancée en utilisant .NET Reflector.

La question est comment faire pour que cela fonctionne correctement?

EDIT: ajouter 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 
+0

Pouvez-vous afficher la trace de la pile? ou la ligne où l'erreur se produit? – tvanfosson

Répondre

11

Je viens d'essayer quelque chose qui fait ce travail. Le problème ne se produit pas si je ne fais pas l'étape de validation mais bien sûr j'ai besoin de la validation. Cela m'a donné un indice pour la solution.

La méthode ValidationMessage HtmlHelper prend un argument de chaîne qui est le nom de la propriété ou de l'objet de modèle en cours de validation. Je viens de changer ce nom pour être « sexe2 » comme suit:

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

Et j'ai changé le code de validation de se référer à ce nouveau nom (même si cette propriété n'existe pas, il fonctionne toujours):

if (!gender.HasValue) 
    ModelState.AddModelError("gender2", "gender required"); 

Cela fonctionne comme vous le souhaitez.

J'aurais pensé que l'autre aurait dû fonctionner, mais c'est une solution de contournement simple et je documente cela ici. Par ailleurs, j'ai essayé de changer la propriété de genre en une chaîne au lieu d'un int nullable, et le même problème se produit exactement. Le travail autour semble toujours être en utilisant un nom de clé différent pour le message de validation.

1

Vous pouvez essayer de changer le genre en une chaîne (M/F) au lieu d'un int et voir si cela fonctionne.

Si vous devez absolument l'avoir comme un int, vous pouvez toujours traduire sur le backend.

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") %> 

base sur votre commentaire, vous pouvez ajouter:

<%= Html.RadioButton("displayGender", 
        string.Empty, 
        true, // this is the default 
        new { @style = "display: none;" }) %> 

Cela garantira que displayGender se réaffecté (il y aura toujours une radio choisie) et je pense que la valeur sera la chaîne .Empty au lieu d'une référence nulle. Si cela fonctionne, vous pouvez essayer de revenir à la valeur null null.

+0

La même chose arrive avec une chaîne au même endroit. Même la chaîne est nulle quand aucun choix n'est fait. Et l'erreur ne se produit pas si je ne fais pas la validation. – davcar

+0

Essayez de garder une chaîne et ajoutez une radio "cachée" qui a la valeur string.empty. Je vais mettre à jour mon exemple. Je pense qu'il ne s'attend pas à ce qu'un bouton radio puisse avoir une valeur nulle, donc il ne vérifie pas avant d'essayer de le convertir. – tvanfosson

+0

Ah, je vois, intéressant d'avoir un bouton radio par défaut caché. Merci pour l'idée. – davcar

1

Essayez d'ajouter la ligne de code suivante après la ModelState.AddModelError():

ModelState.SetModelValue("gender", ValueProvider["gender"]); 
7

Ceci est très similaire, sinon égale à la question de case à cocher: La méthode d'aide Html.Checkbox() génère un champ caché avec un faux valeur. Si ce champ était manquant, le navigateur n'enverrait aucune donnée pour les boîtes non encapsulées. Cependant, un radiobutton est censé avoir une valeur et les valeurs possibles peuvent être plus d'une. Dans ce cas, il n'est pas si facile de gérer le cas de non-sélection, ce qui, je suppose, est la raison pour laquelle ce n'est pas le cas.

La solution pour moi était d'ajouter un champ caché comme suit:

<%= Html.RadioButton("gender", 1) %> Male 
<%= Html.RadioButton("gender", 2) %> Female 
<%= Html.Hidden("gender", null) %> 
1

Si vous voulez fil dans la validation côté client. Sautez l'assistant html et écrivez à la main vos radios, en leur donnant des attributs pour data-val et data-val-required. Comme ça.

<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."/>