Fix #620, Remove legacy / non-unobtrusive client side validation

- remove `ViewContext.UnobtrusiveJavaScriptEnabled` property and all references
- avoid `ViewContext.GetFormContextForClientValidation()` calls since
  ternary expression is more explicit and we were inconsistent
- improve `ValidationMessage()` comments
- don't treat `ModelState.IsValid` as if it were still nullable
This commit is contained in:
dougbu 2014-07-25 16:28:52 -07:00
parent b0d52f73fd
commit b5dcc9895d
4 changed files with 22 additions and 70 deletions

View File

@ -455,16 +455,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
string tag) string tag)
{ {
var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null; var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
if (ViewData.ModelState.IsValid && (formContext == null || excludePropertyErrors))
if (ViewData.ModelState.IsValid == true)
{ {
if (formContext == null || // No client side validation/updates
ViewContext.UnobtrusiveJavaScriptEnabled && return HtmlString.Empty;
excludePropertyErrors)
{
// No client side validation/updates
return HtmlString.Empty;
}
} }
string wrappedMessage; string wrappedMessage;
@ -483,6 +477,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
wrappedMessage = null; 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 htmlSummary = new StringBuilder();
var modelStates = ValidationHelpers.GetModelStateList(ViewData, excludePropertyErrors); var modelStates = ValidationHelpers.GetModelStateList(ViewData, excludePropertyErrors);
@ -514,7 +510,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var divBuilder = new TagBuilder("div"); var divBuilder = new TagBuilder("div");
divBuilder.MergeAttributes(htmlAttributes); divBuilder.MergeAttributes(htmlAttributes);
if (ViewData.ModelState.IsValid == true) if (ViewData.ModelState.IsValid)
{ {
divBuilder.AddCssClass(HtmlHelper.ValidationSummaryValidCssClassName); divBuilder.AddCssClass(HtmlHelper.ValidationSummaryValidCssClassName);
} }
@ -525,23 +521,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
divBuilder.InnerHtml = wrappedMessage + unorderedList.ToString(TagRenderMode.Normal); divBuilder.InnerHtml = wrappedMessage + unorderedList.ToString(TagRenderMode.Normal);
if (formContext != null) if (formContext != null && !excludePropertyErrors)
{ {
if (ViewContext.UnobtrusiveJavaScriptEnabled) // Inform the client where to replace the list of property errors after validation.
{ divBuilder.MergeAttribute("data-valmsg-summary", "true");
if (!excludePropertyErrors)
{
// Only put errors in the validation summary if they're supposed to be included there
divBuilder.MergeAttribute("data-valmsg-summary", "true");
}
}
else
{
// client validation summaries need an ID
divBuilder.GenerateId("validationSummary", IdAttributeDotReplacement);
formContext.ValidationSummaryId = divBuilder.Attributes["id"];
formContext.ReplaceValidationSummary = !excludePropertyErrors;
}
} }
return divBuilder.ToHtmlString(TagRenderMode.Normal); return divBuilder.ToHtmlString(TagRenderMode.Normal);
@ -631,13 +614,12 @@ namespace Microsoft.AspNet.Mvc.Rendering
return GetValidationAttributes(name, metadata: null); return GetValidationAttributes(name, metadata: null);
} }
// Only render attributes if unobtrusive client-side validation is enabled, and then only if we've // 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. Also, if there's no form context, // never rendered validation for a field with this name in this form.
// then we can't render the attributes (we'd have no <form> to attach them to).
protected IDictionary<string, object> GetValidationAttributes(string name, ModelMetadata metadata) protected IDictionary<string, object> GetValidationAttributes(string name, ModelMetadata metadata)
{ {
var formContext = ViewContext.GetFormContextForClientValidation(); var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
if (!ViewContext.UnobtrusiveJavaScriptEnabled || formContext == null) if (formContext == null)
{ {
return null; return null;
} }
@ -787,25 +769,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
// method is an explicit parameter, so it takes precedence over the htmlAttributes. // method is an explicit parameter, so it takes precedence over the htmlAttributes.
tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), replaceExisting: true); tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), replaceExisting: true);
var traditionalJavascriptEnabled = ViewContext.ClientValidationEnabled &&
!ViewContext.UnobtrusiveJavaScriptEnabled;
if (traditionalJavascriptEnabled)
{
// TODO revive ViewContext.FormIdGenerator(), WebFx-199
// forms must have an ID for client validation
var formName = "form" + new Guid().ToString();
tagBuilder.GenerateId(formName, IdAttributeDotReplacement);
}
ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag)); ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
var theForm = CreateForm();
if (traditionalJavascriptEnabled) return CreateForm();
{
ViewContext.FormContext.FormId = tagBuilder.Attributes["id"];
}
return theForm;
} }
protected virtual HtmlString GenerateHidden( protected virtual HtmlString GenerateHidden(
@ -1279,8 +1245,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "expression"); throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "expression");
} }
var formContext = ViewContext.GetFormContextForClientValidation(); var formContext = ViewContext.ClientValidationEnabled ? ViewContext.FormContext : null;
if (!ViewData.ModelState.ContainsKey(modelName) && formContext == null) if (!ViewData.ModelState.ContainsKey(modelName) && formContext == null)
{ {
return null; return null;
@ -1327,18 +1292,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
if (formContext != null) if (formContext != null)
{ {
builder.MergeAttribute("data-valmsg-for", modelName);
var replaceValidationMessageContents = string.IsNullOrEmpty(message); var replaceValidationMessageContents = string.IsNullOrEmpty(message);
builder.MergeAttribute("data-valmsg-replace",
if (ViewContext.UnobtrusiveJavaScriptEnabled) replaceValidationMessageContents.ToString().ToLowerInvariant());
{
builder.MergeAttribute("data-valmsg-for", modelName);
builder.MergeAttribute("data-valmsg-replace",
replaceValidationMessageContents.ToString().ToLowerInvariant());
}
// TODO: (WebFX-217) Add support for Unobtrusive JS disabled -
// Modify the field metadata to add the validation message,
// Add the client validation id in the field metadata
} }
return builder.ToHtmlString(TagRenderMode.Normal); return builder.ToHtmlString(TagRenderMode.Normal);

View File

@ -35,8 +35,6 @@ namespace Microsoft.AspNet.Mvc.Rendering
protected virtual void GenerateEndForm() protected virtual void GenerateEndForm()
{ {
_viewContext.Writer.Write("</form>"); _viewContext.Writer.Write("</form>");
// TODO revive viewContext.OutputClientValidation(), this requires GetJsonValidationMetadata(), GitHub #163
_viewContext.FormContext = null; _viewContext.FormContext = null;
} }

View File

@ -27,7 +27,6 @@ namespace Microsoft.AspNet.Mvc
Writer = writer; Writer = writer;
_formContext = _defaultFormContext; _formContext = _defaultFormContext;
UnobtrusiveJavaScriptEnabled = true;
ClientValidationEnabled = true; ClientValidationEnabled = true;
ValidationSummaryMessageElement = "span"; ValidationSummaryMessageElement = "span";
ValidationMessageElement = "span"; ValidationMessageElement = "span";
@ -41,7 +40,6 @@ namespace Microsoft.AspNet.Mvc
: base(viewContext) : base(viewContext)
{ {
_formContext = viewContext.FormContext; _formContext = viewContext.FormContext;
UnobtrusiveJavaScriptEnabled = viewContext.UnobtrusiveJavaScriptEnabled;
ClientValidationEnabled = viewContext.ClientValidationEnabled; ClientValidationEnabled = viewContext.ClientValidationEnabled;
ValidationSummaryMessageElement = viewContext.ValidationSummaryMessageElement; ValidationSummaryMessageElement = viewContext.ValidationSummaryMessageElement;
ValidationMessageElement = viewContext.ValidationMessageElement; ValidationMessageElement = viewContext.ValidationMessageElement;
@ -64,8 +62,6 @@ namespace Microsoft.AspNet.Mvc
} }
} }
public bool UnobtrusiveJavaScriptEnabled { get; set; }
public bool ClientValidationEnabled { get; set; } public bool ClientValidationEnabled { get; set; }
/// <summary> /// <summary>

View File

@ -26,9 +26,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public string ErrorMessage { get; private set; } public string ErrorMessage { get; private set; }
/// <summary> /// <summary>
/// Identifier of the <see cref="ModelClientValidationRule"/>. If client-side unobtrustive validation is /// Identifier of the <see cref="ModelClientValidationRule"/>. If client-side validation is enabled, default
/// enabled, use this <see langref="string"/> as part of the generated "data-val" attribute name. Must be /// validation attribute generator uses this <see langref="string"/> as part of the generated "data-val"
/// unique in the set of enabled validation rules. /// attribute name. Must be unique in the set of enabled validation rules.
/// </summary> /// </summary>
public string ValidationType { get; private set; } public string ValidationType { get; private set; }