web-dev-qa-db-fra.com

Modèle ValidationSummary personnalisé Asp.net MVC 3

Je travaille sur un projet avec Asp.Net MVC3

Dans une vue j'ai @Html.ValidationSummary(true) et comme d'habitude il produit 

<div class="validation-summary-errors">
    <ul>
        <li>Something bad Happened!</li>
    </ul>
</div>

Comment puis-je étendre ce résumé de validation à MyValidationSummary et produire le modèle de code html à peu près comme ceci: 

<div class="notification warning"> 
    <span></span> 
    <div class="text"> <p>Something bad Happened!</p> </div> 
</div>
58
Dynamikus

This question détaille la procédure d’écriture du résumé de validation personnalisé.

EDIT Cela fera ce que vous voulez:

public static class LinqExt 
{
    public static string MyValidationSummary(this HtmlHelper helper, string validationMessage="")
    {
        string retVal = "";
        if (helper.ViewData.ModelState.IsValid)
            return "";

        retVal += "<div class='notification-warnings'><span>";
        if (!String.IsNullOrEmpty(validationMessage))
            retVal += helper.Encode(validationMessage);
        retVal += "</span>";
        retVal += "<div class='text'>";
        foreach (var key in helper.ViewData.ModelState.Keys) 
        {
            foreach(var err in helper.ViewData.ModelState[key].Errors)
                retVal += "<p>" + helper.Encode(err.ErrorMessage) + "</p>";
        }
        retVal += "</div></div>";
        return retVal.ToString();
    }
}

Le code est explicite. en énumérant simplement les erreurs de modèle et les erreurs d’emballage dans l’élément dom de votre choix. Il y a une erreur si je l'utilise comme:

<%:Html.MyValidationSummary()%>

Il affichera les balises HTML sur la page sous forme de texte plutôt que de les restituer. 

<%=Html.MyValidationSummary()%>

Cela fonctionne bien.

45

Mon approche consiste à utiliser un ValidationSummary.cshtml personnalisé:

@model ModelStateDictionary

@if(!Model.IsValid)
{
    <div class="validation-summary-errors">
        <ul>
            @foreach (var modelError in 
                     Model.SelectMany(keyValuePair => keyValuePair.Value.Errors))
            {
                <li>@modelError.ErrorMessage</li>
            }
        </ul>
    </div>
}

Placez cette vue partielle dans votre dossier partagé et faites-y référence à partir de votre code:

@Html.Partial("_ValidationSummary", ViewData.ModelState);

De cette façon, vous gardez le plein contrôle de votre code HTML.

129
flo scheiwiller

En me basant sur flos's answer , je l’ai rendu compatible avec la validation jQuery Unobtrusive de Microsoft et j’ai ajouté le style à 3 panneaux de Bootstrap. Voici le nouveau code:

@model ModelStateDictionary

<div class="@(Html.ViewData.ModelState.IsValid ? "validation-summary-valid" : "validation-summary-errors") panel panel-danger"
     data-valmsg-summary="true">
    <div class="panel-heading">
        Please, correct the following errors:
    </div>
    <div class="panel-body">
        <ul>
            @foreach(var modelError in Model.SelectMany(keyValuePair => keyValuePair.Value.Errors))
            {
                <li>@modelError.ErrorMessage</li>
            }
        </ul>
    </div>
</div>

Vous pouvez lire à ce sujet en détail ici:

Création d'un fichier ASP.NET MVC @ Html.ValidationSummary personnalisé stylé avec le panneau Bootstrap 3

J'ai également créé un exemple de projet ASP.NET MVC pour afficher ce ValidationSummary personnalisé en action. Obtenez-le ici:

https://github.com/leniel/AspNetMvcCustomHtmlValidationSummary

21
Leniel Maccaferri

Je poste juste ma réponse ici parce que ça marche bien pour moi;)

J'utilise une méthode d'extension simple qui prend une MvcHtmlString et la décode en HTML:

    public static MvcHtmlString ToMvcHtmlString(this MvcHtmlString htmlString)
    {
        if (htmlString != null)
        {
            return new MvcHtmlString(HttpUtility.HtmlDecode(htmlString.ToString()));
        }
        return null;
    }

Pour ajouter ceci, j'ajoute l'assistant de résumé de validation à mon chstml comme ceci:

@Html.ValidationSummary(true).ToMvcHtmlString()

Cela signifie que je peux ajouter du HTML personnalisé à mes résumés de validation:

ModelState.AddModelError("", "<p>This message can have html in it</p>");

Et je peux même ajouter du HTML personnalisé à mes messages de validation de champ:

ModelState.AddModelError("MyField", "<p>This message can have html in it</p>");

Et pour que mes messages de validation sur le terrain fonctionnent avec HTML:

@Html.ValidationMessageFor(model => model.MyField).ToMvcHtmlString();
2
Matt Roberts

Ajout de styles associés:

.field-validation-error {
    color: #b94a48;
}

.field-validation-valid {
    display: none;
}

input.input-validation-error {
    border: 1px solid #b94a48;
}

input[type="checkbox"].input-validation-error {
    border: 0 none;
}

.validation-summary-errors {
    color: #b94a48;
}

.validation-summary-valid {
    display: none;
}

1
Yovav

Je viens juste de faire quelque chose de similaire pour la validation côté serveur uniquement (par exemple, vérifier le contenu du fichier) et je me suis retrouvé complètement en train d'usurper le @ Html.ValidationSummary avec tout à fait un joli petit travail autour.

Nous avons une classe BaseController qui étend Controller et à l'intérieur de laquelle nous substituons la méthode OnActionExecuting à plusieurs fins . Nous créons une nouvelle liste dans ViewBag pour nos messages d'erreur et nous nous assurons qu'elle soit initialisée avant. Ensuite, nous pouvons ajouter nos erreurs pour y être affichées et les afficher à l'écran.

Pour les besoins de cette question, cela ressemblerait à ceci.

public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (ViewBag.ErrorsList == null)
        {
            ViewBag.ErrorsList = new List<string>();
        }
    }
}

Ensuite, dans notre _Layout.cshtml, ajoutez ce qui suit ci-dessus votre @RenderBody ()

@if(ViewBag.ErrorsList.Count > 0)
{
    <div class="container margin-top-10 alert alert-danger">
        <h3><i class="glyphicon glyphicon-warning-sign"></i></h3><br/>
        @foreach (string error in @ViewBag.ErrorsList)
        {
            @error <br/>
        }
    </div>
    @RenderBody()
}

Maintenant, chaque fois qu'une erreur survient côté serveur que nous voulons afficher comme message d'erreur de validation, nous l'ajoutons simplement à notre ViewBag.ErrorsList

ViewBag.ErrorsList.Add("Something bad happened...");

Et voila, un conteneur personnalisé pour vos messages d'erreur de validation côté serveur avec tous les styles que vous souhaitez, avec des erreurs transmises de la même manière que ValidationSummary.

1
Dean Puckett

Je voulais montrer seulement le message de haut niveau et rien d'autre. Nous avons déjà la validation à côté des champs ci-dessous. Utilisation de la solution de @ Leniel-Macaferi, voici ce que j'ai fait pour que cela fonctionne avec la validation jQuery: (added style = "display: none;")

<div class="@(Html.ViewData.ModelState.IsValid ? "validation-summary-valid" : "validation-summary-errors")"
     data-valmsg-summary="true">
    <div>
        There are still some fields not filled in before we can submit this. Please correct.
    </div>
    <div style="display: none;">
        <ul>
            @foreach (var modelError in Model.SelectMany(keyValuePair => keyValuePair.Value.Errors))
            {
                <li>@modelError.ErrorMessage</li>
            }
        </ul>
    </div>
</div>
0
Rob Koch