可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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>
回答1:
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.
回答2:
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.
回答3:
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
回答4:
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();
回答5:
Adding related styles:
.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;
}
回答6:
I've just had to do something similar for server side validation only ( e.g checking file contents) and have ended up completely usurping the @Html.ValidationSummary altogether with quite a nice little work around.
We have a BaseController class that extends Controller, and inside we override the OnActionExecuting method for several purposes.
We create a new list in ViewBag for our error messages and ensure before any action runs it is initialized. Then we can add our errors to be displayed to it, and display on screen.
For the purposes of this question it would look like this.
public class BaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (ViewBag.ErrorsList == null)
{
ViewBag.ErrorsList = new List<string>();
}
}
}
Then in our _Layout.cshtml add the following above your @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()
}
Now whenever an error occurs server side that we want to display as a validation error message we simply add it to our ViewBag.ErrorsList
ViewBag.ErrorsList.Add("Something bad happened...");
And voila, one custom container for your server side validation error messages with any styles you want on it, with errors passed in the same manner as ValidationSummary.
回答7:
I wanted to show just top-level message and nothing else. We already have validation next to the fields below. Working off @Leniel-Macaferi's solution this is what I did to make it work with jQuery validation: (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>