diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs
index 06b9968f4a..92eb6e23f0 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/Html/HtmlHelper.cs
@@ -100,7 +100,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
}
- protected IModelMetadataProvider MetadataProvider { get; private set; }
+ ///
+ public IModelMetadataProvider MetadataProvider { get; private set; }
///
public HtmlString ActionLink(
@@ -328,10 +329,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
///
- public virtual HtmlString Name(string name)
+ public HtmlString Name(string name)
{
- var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
- return new HtmlString(Encode(fullName));
+ return GenerateName(name);
}
///
@@ -449,85 +449,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
///
- public virtual HtmlString ValidationSummary(bool excludePropertyErrors,
+ public HtmlString ValidationSummary(bool excludePropertyErrors,
string message,
IDictionary htmlAttributes,
string tag)
{
- var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
- if (ViewData.ModelState.IsValid && (formContext == null || excludePropertyErrors))
- {
- // No client side validation/updates
- return HtmlString.Empty;
- }
-
- string wrappedMessage;
- if (!string.IsNullOrEmpty(message))
- {
- if (string.IsNullOrEmpty(tag))
- {
- tag = ViewContext.ValidationSummaryMessageElement;
- }
- var messageTag = new TagBuilder(tag);
- messageTag.SetInnerText(message);
- wrappedMessage = messageTag.ToString(TagRenderMode.Normal) + Environment.NewLine;
- }
- else
- {
- wrappedMessage = null;
- }
-
- // If excludePropertyErrors is true, describe any validation issue with the current model in a single item.
- // Otherwise, list individual property errors.
- var htmlSummary = new StringBuilder();
- var modelStates = ValidationHelpers.GetModelStateList(ViewData, excludePropertyErrors);
-
- foreach (var modelState in modelStates)
- {
- foreach (var modelError in modelState.Errors)
- {
- var errorText = ValidationHelpers.GetUserErrorMessageOrDefault(modelError, modelState: null);
-
- if (!string.IsNullOrEmpty(errorText))
- {
- var listItem = new TagBuilder("li");
- listItem.SetInnerText(errorText);
- htmlSummary.AppendLine(listItem.ToString(TagRenderMode.Normal));
- }
- }
- }
-
- if (htmlSummary.Length == 0)
- {
- htmlSummary.AppendLine(HiddenListItem);
- }
-
- var unorderedList = new TagBuilder("ul")
- {
- InnerHtml = htmlSummary.ToString()
- };
-
- var divBuilder = new TagBuilder("div");
- divBuilder.MergeAttributes(htmlAttributes);
-
- if (ViewData.ModelState.IsValid)
- {
- divBuilder.AddCssClass(HtmlHelper.ValidationSummaryValidCssClassName);
- }
- else
- {
- divBuilder.AddCssClass(HtmlHelper.ValidationSummaryCssClassName);
- }
-
- divBuilder.InnerHtml = wrappedMessage + unorderedList.ToString(TagRenderMode.Normal);
-
- if (formContext != null && !excludePropertyErrors)
- {
- // Inform the client where to replace the list of property errors after validation.
- divBuilder.MergeAttribute("data-valmsg-summary", "true");
- }
-
- return divBuilder.ToHtmlString(TagRenderMode.Normal);
+ return GenerateValidationSummary(excludePropertyErrors, message, htmlAttributes, tag);
}
///
@@ -549,7 +476,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
///
- public virtual HtmlString TextArea(string name, string value, int rows, int columns, object htmlAttributes)
+ public HtmlString TextArea(string name, string value, int rows, int columns, object htmlAttributes)
{
var metadata = ExpressionMetadataProvider.FromStringExpression(name, ViewData, MetadataProvider);
if (value != null)
@@ -609,14 +536,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
return null;
}
- protected IDictionary GetValidationAttributes(string name)
- {
- return GetValidationAttributes(name, metadata: null);
- }
-
// Only render attributes if client-side validation is enabled, and then only if we've
// never rendered validation for a field with this name in this form.
- protected IDictionary GetValidationAttributes(string name, ModelMetadata metadata)
+ protected virtual IDictionary GetValidationAttributes(ModelMetadata metadata, string name)
{
var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
if (formContext == null)
@@ -631,7 +553,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
formContext.RenderedField(fullName, true);
- var clientRules = GetClientValidationRules(name, metadata);
+ var clientRules = GetClientValidationRules(metadata, name);
return UnobtrusiveValidationAttributesGenerator.GetValidationAttributes(clientRules);
}
@@ -875,6 +797,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
htmlAttributes: htmlAttributes);
}
+ protected virtual HtmlString GenerateName(string name)
+ {
+ var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
+ return new HtmlString(Encode(fullName));
+ }
+
protected virtual HtmlString GeneratePassword(ModelMetadata metadata, string name, object value,
object htmlAttributes)
{
@@ -1043,7 +971,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
}
- tagBuilder.MergeAttributes(GetValidationAttributes(name, metadata));
+ tagBuilder.MergeAttributes(GetValidationAttributes(metadata, name));
return tagBuilder.ToHtmlString(TagRenderMode.Normal);
}
@@ -1094,7 +1022,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
tagBuilder.MergeAttribute("name", fullName, true);
- tagBuilder.MergeAttributes(GetValidationAttributes(name, metadata));
+ tagBuilder.MergeAttributes(GetValidationAttributes(metadata, name));
// If there are any errors for a named field, we add this CSS attribute.
if (modelState != null && modelState.Errors.Count > 0)
@@ -1212,7 +1140,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
tagBuilder.AddCssClass(ValidationInputCssClassName);
}
- tagBuilder.MergeAttributes(GetValidationAttributes(name, metadata));
+ tagBuilder.MergeAttributes(GetValidationAttributes(metadata, name));
if (inputType == InputType.CheckBox)
{
@@ -1302,6 +1230,88 @@ namespace Microsoft.AspNet.Mvc.Rendering
return builder.ToHtmlString(TagRenderMode.Normal);
}
+ protected virtual HtmlString GenerateValidationSummary(
+ bool excludePropertyErrors,
+ string message,
+ IDictionary htmlAttributes,
+ string tag)
+ {
+ var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
+ if (ViewData.ModelState.IsValid && (formContext == null || excludePropertyErrors))
+ {
+ // No client side validation/updates
+ return HtmlString.Empty;
+ }
+
+ string wrappedMessage;
+ if (!string.IsNullOrEmpty(message))
+ {
+ if (string.IsNullOrEmpty(tag))
+ {
+ tag = ViewContext.ValidationSummaryMessageElement;
+ }
+ var messageTag = new TagBuilder(tag);
+ messageTag.SetInnerText(message);
+ wrappedMessage = messageTag.ToString(TagRenderMode.Normal) + Environment.NewLine;
+ }
+ else
+ {
+ wrappedMessage = null;
+ }
+
+ // If excludePropertyErrors is true, describe any validation issue with the current model in a single item.
+ // Otherwise, list individual property errors.
+ var htmlSummary = new StringBuilder();
+ var modelStates = ValidationHelpers.GetModelStateList(ViewData, excludePropertyErrors);
+
+ foreach (var modelState in modelStates)
+ {
+ foreach (var modelError in modelState.Errors)
+ {
+ var errorText = ValidationHelpers.GetUserErrorMessageOrDefault(modelError, modelState: null);
+
+ if (!string.IsNullOrEmpty(errorText))
+ {
+ var listItem = new TagBuilder("li");
+ listItem.SetInnerText(errorText);
+ htmlSummary.AppendLine(listItem.ToString(TagRenderMode.Normal));
+ }
+ }
+ }
+
+ if (htmlSummary.Length == 0)
+ {
+ htmlSummary.AppendLine(HiddenListItem);
+ }
+
+ var unorderedList = new TagBuilder("ul")
+ {
+ InnerHtml = htmlSummary.ToString()
+ };
+
+ var divBuilder = new TagBuilder("div");
+ divBuilder.MergeAttributes(htmlAttributes);
+
+ if (ViewData.ModelState.IsValid)
+ {
+ divBuilder.AddCssClass(HtmlHelper.ValidationSummaryValidCssClassName);
+ }
+ else
+ {
+ divBuilder.AddCssClass(HtmlHelper.ValidationSummaryCssClassName);
+ }
+
+ divBuilder.InnerHtml = wrappedMessage + unorderedList.ToString(TagRenderMode.Normal);
+
+ if (formContext != null && !excludePropertyErrors)
+ {
+ // Inform the client where to replace the list of property errors after validation.
+ divBuilder.MergeAttribute("data-valmsg-summary", "true");
+ }
+
+ return divBuilder.ToHtmlString(TagRenderMode.Normal);
+ }
+
protected virtual HtmlString GenerateValue(string name, object value, string format, bool useViewData)
{
var fullName = ViewData.TemplateInfo.GetFullHtmlFieldName(name);
@@ -1336,9 +1346,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
return new HtmlString(Encode(resolvedValue));
}
- protected virtual IEnumerable GetClientValidationRules(
- string name,
- ModelMetadata metadata)
+ ///
+ public IEnumerable GetClientValidationRules(
+ ModelMetadata metadata,
+ string name)
{
var actionBindingContext = _actionBindingContextProvider.GetActionBindingContextAsync(ViewContext).Result;
metadata = metadata ??
diff --git a/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelper.cs b/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelper.cs
index 2ce1b6c12c..21c27dd0a3 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Rendering/IHtmlHelper.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
+using Microsoft.AspNet.Mvc.ModelBinding;
namespace Microsoft.AspNet.Mvc.Rendering
{
@@ -23,6 +24,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
///
string IdAttributeDotReplacement { get; set; }
+ ///
+ /// Gets the metadata provider. Intended for use in extension methods.
+ ///
+ IModelMetadataProvider MetadataProvider { get; }
+
///
/// Gets the view bag.
///
@@ -245,6 +251,17 @@ namespace Microsoft.AspNet.Mvc.Rendering
/// The ID of the HTML element.
string GenerateIdFromName(string name);
+ ///
+ /// Returns information about about client validation rules for the given or
+ /// . Intended for use in extension methods.
+ ///
+ /// Metadata about the of interest.
+ /// Expression name, relative to the current model. Used to determine
+ /// when is ; ignored
+ /// otherwise.
+ /// An containing the relevant rules.
+ IEnumerable GetClientValidationRules(ModelMetadata metadata, string name);
+
///
/// Render an input element of type "hidden".
///