2011-11-22 12 views
11

Vedo che il mio ModelState.Values[x].Errors è popolato correttamente con i due errori di convalida per una singola proprietà.Come visualizzare più errori di convalida con @ Html.ValidationMessageFor?

Se utilizzo un @Html.ValidationSummary() a mio avviso, visualizza correttamente entrambi gli errori .... anche se nella parte superiore della pagina e non accanto all'ingresso non valido.

Utilizzo di @Html.ValidationMessageFor(model => model.MyProperty) visualizza il primo errore solo per quella proprietà!

Come posso mostrare entrambi gli errori, prossimi all'ingresso appropriato?

risposta

10

Una soluzione è quella di implementare il proprio metodo di estensione su HtmlHelper che fa qualcosa di diverso per il comportamento predefinito ValidationMessageFor. Il metodo @ Html.ValidationMessagesFor esempio riportato di seguito verrà concatenare più messaggi di errore che sono stati aggiunti alla ModelState durante lato server convalida (solo).

public static MvcHtmlString ValidationMessagesFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null) 
{ 
    var propertyName = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).PropertyName; 
    var modelState = htmlHelper.ViewData.ModelState; 

    // If we have multiple (server-side) validation errors, collect and present them. 
    if (modelState.ContainsKey(propertyName) && modelState[propertyName].Errors.Count > 1) 
    { 
     var msgs = new StringBuilder(); 
     foreach (ModelError error in modelState[propertyName].Errors) 
     { 
      msgs.AppendLine(error.ErrorMessage); 
     } 

     // Return standard ValidationMessageFor, overriding the message with our concatenated list of messages. 
     return htmlHelper.ValidationMessageFor(expression, msgs.ToString(), htmlAttributes as IDictionary<string, object> ?? htmlAttributes); 
    } 

    // Revert to default behaviour. 
    return htmlHelper.ValidationMessageFor(expression, null, htmlAttributes as IDictionary<string, object> ?? htmlAttributes); 
} 

Questo è utile se si dispone di convalida business personalizzata si sta applicando in una raccolta che appartiene al modello (ad esempio, i totali dei controlli incrociati), o il controllo del modello nel suo complesso.

Un esempio di utilizzare questo, in cui una collezione di Order.LineItems vengono convalidati sul lato server:

@using MyHtmlHelperExtensions // namespace containing ValidationMessagesFor 
@using (Html.BeginForm()) 
{ 
    @Html.LabelFor(m => m.LineItems) 
    <ul> 
     @Html.EditorFor(m => m.LineItems) 
    </ul> 
    @Html.ValidationMessagesFor(m => m.LineItems) 
} 
+0

bella soluzione. Funziona con viste nidificate con viewmodels? ho dovuto aggiungere il seguente: 'var = relativePropertyName ExpressionHelper.GetExpressionText (espressione);' ' var propertyName = String.Format ("{0} {2} {1}", htmlHelper.ViewContext.ViewData.TemplateInfo. HtmlFieldPrefix, relativePropertyName, (String.IsNullOrWhiteSpace (relativePropertyName)? String.Empty: ".")); ' – Fiddles

+0

Il modo più semplice per farlo funzionare con viste nidificate è: propertyName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName (propertyName –

+0

Risposta eccellente, e funziona. Tranne che entrambi i miei errori sono sulla stessa linea. Ho bisogno che ogni messaggio di errore sia sulla propria linea. Con un tag
tra l'esempio – theB3RV

3

La risposta Dave A-W fornito è essenzialmente corretti ma non funziona in tutti i casi. Per ottenere il nome della proprietà corretto il codice sorgente di MVC 3 utilizza:

var propertyName = ExpressionHelper.GetExpressionText(expression); 

Questo si prende cura di eventuali prefissi nei dati del modulo

Problemi correlati