Custom ValidationSummary template Asp.net MVC 3
I am working on a project with Asp.Net MVC3
In a View I have @Html.ValidationSummary(true)
and as usually it produces
<div class="validation-summary-errors">
<ul>
<li>Something bad Happened!</li>
</ul>
</div>
How can I extend this ValidationSummary to MyValidationSummary and produces the Html Code template something like this:
<div class="notification warning">
<span></span>
<div class="text"> <p>Something bad Happened!</p> </div>
</div>
My approach is to use a custom ValidationSummary.cshtml
:
@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>
}
Put this partial view in your Shared folder and refer to it from your code:
@Html.Partial("_ValidationSummary", ViewData.ModelState);
This way you remain in full control of your html.
This question details the procedure of writing custom validation summary.
EDIT This will do what you want:
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();
}
}
The code is self explanatory; just enumerating through modelstate errors and wrapping errors in dom element of your choice. There is an error that is if i use it like:
<%:Html.MyValidationSummary()%>
It will display html tags on the page as text rather than rendering it.
<%=Html.MyValidationSummary()%>
This works fine.
Building upon flos's answer, I made it compatible with Microsoft's jQuery Unobtrusive Validation and added Bootstrap's 3 panel styling. Here's the new 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>
You can read about it in full detail here:
Creating a custom ASP.NET MVC @Html.ValidationSummary styled with Bootstrap 3 panel
I also created a sample ASP.NET MVC project to show this custom ValidationSummary in action. Get it here:
https://github.com/leniel/AspNetMvcCustomHtmlValidationSummary
Just posting my answer here because it's working well for me ;)
I use a simple extension method that takes an MvcHtmlString
and decodes it back to HTML:
public static MvcHtmlString ToMvcHtmlString(this MvcHtmlString htmlString)
{
if (htmlString != null)
{
return new MvcHtmlString(HttpUtility.HtmlDecode(htmlString.ToString()));
}
return null;
}
To plumb this in, I add the validation summary helper to my chstml like this:
@Html.ValidationSummary(true).ToMvcHtmlString()
This means, I can add custom HTML to my validation summaries:
ModelState.AddModelError("", "<p>This message can have html in it</p>");
And I can even add custom HTML to my field validation messages:
ModelState.AddModelError("MyField", "<p>This message can have html in it</p>");
And to get my field validation messages to work with HTML:
@Html.ValidationMessageFor(model => model.MyField).ToMvcHtmlString();