2009-05-05 5 views
8

je le code suivant dans une vue fortement typée dans ma demande:NullReferenceException problème ASP.NET MVC Textbox HtmlHelper

<td> 
<label for="TriageStartDate">Triage Start:</label> 
<%= Html.TextBox("TriageStartDate", crit.TriageStartDate, new { maxlength = 10, size = 12 })%> 
<%= Html.ValidationMessage("TriageStartDate", "*") %> 
</td> 

La variable est passée Crit dans ViewData et est jeté à un strongly- objet typé dans la vue à l'aide:

PatientSearchCriteria crit = (PatientSearchCriteria)ViewData["criteria"];  

la TriageStartDate propriété est une propriété de chaîne définie sur l'objet comme ceci:

public string TriageStartDate { get; set; } 

J'ai une routine de validation dans l'objet métier qui vérifie cette propriété pour les dates non valides. La routine de validation est appelée dans mon contrôleur, et dans le contrôleur j'ajoute une ModelError à ModelState lorsqu'une date invalide est trouvée (par exemple "4/34/2009"). Cela devrait entraîner la réaffichage de la vue et l'affichage du résumé de validation et du message.

Toutefois, le code se bloque sur la ligne Html.TextBox avec une exception NullReferenceException non gérée. Le code seulement se bloque lorsque des dates non valides sont entrées, ce qui ne devrait probablement pas avoir d'importance puisque la propriété est une chaîne de toute façon, et il devrait juste afficher la date invalide dans la zone de texte.

Une idée de ce qui se passe ici? Je pensais que cela pourrait être une chose Html.Encode, mais les dates valables s'affichent sans problème. Lorsque je casse sur cette ligne en mode débogage, je peux voir la valeur "4/34/2009" dans la propriété TriageStartDate, et la variable crit elle-même n'est pas nulle, donc je me demande quel objet est null?

BTW, les premières lignes de la trace de la pile ressembler à ceci:

[NullReferenceException: Object reference not set to an instance of an object.] 
    System.Web.Mvc.HtmlHelper.GetModelStateValue(String key, Type destinationType) +63 
    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) +519 
    System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Object value, IDictionary`2 htmlAttributes) +34 
    System.Web.Mvc.Html.InputExtensions.TextBox(HtmlHelper htmlHelper, String name, Object value, Object htmlAttributes) +62 

Voici mon code de validation (qui pourrait ne pas être assez). Dans l'objet métier:

public override IEnumerable<ValidationError> GetValidationErrors() 
{ 
    // check for valid start date 
    if (!String.IsNullOrEmpty(TriageStartDate)) 
    { 
     DateTime critStartDate; 
     if (!DateTime.TryParse(TriageStartDate, out critStartDate)) 
      yield return new ValidationError(String.Format("Invalid triage start date specified: {0}", TriageStartDate), "TriageStartDate"); 
    } 

    // check for valid end date 
    if (!String.IsNullOrEmpty(TriageEndDate)) 
    { 
     DateTime critEndDate; 
     if (!DateTime.TryParse(TriageEndDate, out critEndDate)) 
      yield return new ValidationError(String.Format("Invalid triage end date specified: {0}", TriageEndDate), "TriageEndDate"); 
    } 

    // verify that end date follows start date if both are specified 
    if (!String.IsNullOrEmpty(TriageStartDate) && !String.IsNullOrEmpty(TriageEndDate)) 
    { 
     DateTime startDate; 
     DateTime endDate; 

     if (DateTime.TryParse(TriageStartDate, out startDate) && DateTime.TryParse(TriageEndDate, out endDate)) 
     { 
      if (startDate > endDate) 
       yield return new ValidationError("Triage start date must be before end date", "_FORM"); 
     } 
    } 

    yield break; 
} 

Dans le contrôleur:

// validate search criteria 
    if (!criteria.IsValid) 
    { 
     foreach (ValidationError ve in criteria.GetValidationErrors()) 
     { 
      ModelState.AddModelError(ve.PropertyName, ve.ErrorMessage); 
     } 
    } 

Merci pour tous les indices! Grâce aux suggestions de Craig, j'ai mis à jour le code du contrôleur comme suit, et l'exception de référence nulle a disparu. La solution a fonctionné, mais je ne suis pas certaine de comprendre le raisonnement, car la valeur que l'utilisateur a tenté d'entrer est déjà stockée dans l'objet modèle et j'ai d'autres vues et contrôleurs dans le projet qui affichent les erreurs de validation sans quelque problème que ce soit. Mais, bon, si ça marche ...

// validate search criteria 
    if (!criteria.IsValid) 
    { 
     foreach (ValidationError ve in criteria.GetValidationErrors()) 
     { 
      ModelState.AddModelError(ve.PropertyName, ve.ErrorMessage); 
      ModelState.SetModelValue(ve.PropertyName, form.ToValueProvider()[ve.PropertyName]); 
     } 

    } 
+0

mettre votre code de validation, je pense que le problème est là –

Répondre

9

Une fois que vous appelez AddModelError vous devez appeler SetModelValue. Cela devrait corriger la référence null.

+0

Craig, merci pour la réponse, mais je ne peux trouver aucune méthode SetAttempedValue sur l'un des objets dans le contrôleur ou la vue. Je vois SetModelValue, mais il n'est pas clair pour moi comment utiliser - ou même si je devrais - donné le deuxième paramètre de type ValueProviderResult, que je ne sais pas comment construire. Le modèle contient en réalité la valeur de tentative entrée par l'utilisateur, donc je ne suis pas sûr de l'endroit où cela me laisse. Peut-être profondément sous les couvertures quelque part ASP.NET MVC essaie de convertir la valeur à une date et avoir un problème ?? –

+0

Une façon est avec Form.ToValueProvider() ... –

+0

Merci, Craig. J'ai mis à jour mon code pour contenir le SetModelValue avec la méthode Form.ToValueProvider générant le ValueProviderResult et cela a corrigé l'exception de référence null. Je suis toujours confus, mais mon code fonctionne ... :-) –

1

Je suis tombé dessus car je tapais une question/problème presque identique. (ie, le rendu de ma vue provoquait le lancement d'une mystérieuse NullReferenceException lorsque la valeur de l'utilisateur avait échoué lors de la validation sur un champ particulier. laisser le HtmlHelper faire le travail.

Par exemple: <%= Html.TextArea("FieldName", Model.FieldName) %> jetterait une exception, mais <textarea id="FieldName" name="FieldName"><%= Model.FieldName ></textarea> fonctionnerait parfaitement bien.

Merci de poster la question initiale puisque maintenant je vais devoir faire un peu plus dans la recherche SetModelValue pour voir lequel des deux approches est la meilleure solution ...