diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
index 654d4668c8..8ea3effdd4 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/InputTagHelper.cs
@@ -113,6 +113,15 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName("type")]
public string InputTypeName { get; set; }
+ ///
+ /// The name of the <input> element.
+ ///
+ ///
+ /// Passed through to the generated HTML in all cases. Also used to determine whether is
+ /// valid with an empty .
+ ///
+ public string Name { get; set; }
+
///
/// The value of the <input> element.
///
@@ -146,6 +155,11 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
output.CopyHtmlAttribute("type", context);
}
+ if (Name != null)
+ {
+ output.CopyHtmlAttribute(nameof(Name), context);
+ }
+
if (Value != null)
{
output.CopyHtmlAttribute(nameof(Value), context);
@@ -183,15 +197,27 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
output.Attributes.SetAttribute("type", inputType);
}
+ // Ensure Generator does not throw due to empty "fullName" if user provided a name attribute.
+ IDictionary htmlAttributes = null;
+ if (string.IsNullOrEmpty(For.Name) &&
+ string.IsNullOrEmpty(ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix) &&
+ !string.IsNullOrEmpty(Name))
+ {
+ htmlAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase)
+ {
+ { "name", Name },
+ };
+ }
+
TagBuilder tagBuilder;
switch (inputType)
{
case "hidden":
- tagBuilder = GenerateHidden(modelExplorer);
+ tagBuilder = GenerateHidden(modelExplorer, htmlAttributes);
break;
case "checkbox":
- tagBuilder = GenerateCheckBox(modelExplorer, output);
+ tagBuilder = GenerateCheckBox(modelExplorer, output, htmlAttributes);
break;
case "password":
@@ -200,15 +226,15 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
modelExplorer,
For.Name,
value: null,
- htmlAttributes: null);
+ htmlAttributes: htmlAttributes);
break;
case "radio":
- tagBuilder = GenerateRadio(modelExplorer);
+ tagBuilder = GenerateRadio(modelExplorer, htmlAttributes);
break;
default:
- tagBuilder = GenerateTextBox(modelExplorer, inputTypeHint, inputType);
+ tagBuilder = GenerateTextBox(modelExplorer, inputTypeHint, inputType, htmlAttributes);
break;
}
@@ -248,7 +274,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
return inputTypeHint;
}
- private TagBuilder GenerateCheckBox(ModelExplorer modelExplorer, TagHelperOutput output)
+ private TagBuilder GenerateCheckBox(
+ ModelExplorer modelExplorer,
+ TagHelperOutput output,
+ IDictionary htmlAttributes)
{
if (modelExplorer.ModelType == typeof(string))
{
@@ -282,6 +311,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var renderingMode =
output.TagMode == TagMode.SelfClosing ? TagRenderMode.SelfClosing : TagRenderMode.StartTag;
hiddenForCheckboxTag.TagRenderMode = renderingMode;
+ if (!hiddenForCheckboxTag.Attributes.ContainsKey("name") &&
+ !string.IsNullOrEmpty(Name))
+ {
+ // The checkbox and hidden elements should have the same name attribute value. Attributes will
+ // match if both are present because both have a generated value. Reach here in the special case
+ // where user provided a non-empty fallback name.
+ hiddenForCheckboxTag.MergeAttribute("name", Name);
+ }
if (ViewContext.FormContext.CanRenderAtEndOfForm)
{
@@ -298,10 +335,10 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
modelExplorer,
For.Name,
isChecked: null,
- htmlAttributes: null);
+ htmlAttributes: htmlAttributes);
}
- private TagBuilder GenerateRadio(ModelExplorer modelExplorer)
+ private TagBuilder GenerateRadio(ModelExplorer modelExplorer, IDictionary htmlAttributes)
{
// Note empty string is allowed.
if (Value == null)
@@ -319,10 +356,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
For.Name,
Value,
isChecked: null,
- htmlAttributes: null);
+ htmlAttributes: htmlAttributes);
}
- private TagBuilder GenerateTextBox(ModelExplorer modelExplorer, string inputTypeHint, string inputType)
+ private TagBuilder GenerateTextBox(
+ ModelExplorer modelExplorer,
+ string inputTypeHint,
+ string inputType,
+ IDictionary htmlAttributes)
{
var format = Format;
if (string.IsNullOrEmpty(format))
@@ -338,12 +379,18 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
format = GetFormat(modelExplorer, inputTypeHint, inputType);
}
}
- var htmlAttributes = new Dictionary
- {
- { "type", inputType }
- };
- if (string.Equals(inputType, "file") && string.Equals(inputTypeHint, TemplateRenderer.IEnumerableOfIFormFileName))
+ if (htmlAttributes == null)
+ {
+ htmlAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ }
+
+ htmlAttributes["type"] = inputType;
+ if (string.Equals(inputType, "file") &&
+ string.Equals(
+ inputTypeHint,
+ TemplateRenderer.IEnumerableOfIFormFileName,
+ StringComparison.OrdinalIgnoreCase))
{
htmlAttributes["multiple"] = "multiple";
}
@@ -352,14 +399,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
ViewContext,
modelExplorer,
For.Name,
- value: modelExplorer.Model,
- format: format,
- htmlAttributes: htmlAttributes);
+ modelExplorer.Model,
+ format,
+ htmlAttributes);
}
// Imitate Generator.GenerateHidden() using Generator.GenerateTextBox(). This adds support for asp-format that
// is not available in Generator.GenerateHidden().
- private TagBuilder GenerateHidden(ModelExplorer modelExplorer)
+ private TagBuilder GenerateHidden(ModelExplorer modelExplorer, IDictionary htmlAttributes)
{
var value = For.Model;
if (value is byte[] byteArrayValue)
@@ -367,21 +414,17 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
value = Convert.ToBase64String(byteArrayValue);
}
+ if (htmlAttributes == null)
+ {
+ htmlAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ }
+
// In DefaultHtmlGenerator(), GenerateTextBox() calls GenerateInput() _almost_ identically to how
// GenerateHidden() does and the main switch inside GenerateInput() handles InputType.Text and
// InputType.Hidden identically. No behavior differences at all when a type HTML attribute already exists.
- var htmlAttributes = new Dictionary
- {
- { "type", "hidden" }
- };
+ htmlAttributes["type"] = "hidden";
- return Generator.GenerateTextBox(
- ViewContext,
- modelExplorer,
- For.Name,
- value: value,
- format: Format,
- htmlAttributes: htmlAttributes);
+ return Generator.GenerateTextBox(ViewContext, modelExplorer, For.Name, value, Format, htmlAttributes);
}
// Get a fall-back format based on the metadata.
@@ -462,4 +505,4 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/SelectTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/SelectTagHelper.cs
index c7657f17f1..f0e5dd2d06 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/SelectTagHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/SelectTagHelper.cs
@@ -57,6 +57,15 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(ItemsAttributeName)]
public IEnumerable Items { get; set; }
+ ///
+ /// The name of the <input> element.
+ ///
+ ///
+ /// Passed through to the generated HTML in all cases. Also used to determine whether is
+ /// valid with an empty .
+ ///
+ public string Name { get; set; }
+
///
public override void Init(TagHelperContext context)
{
@@ -89,11 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
var realModelType = For.ModelExplorer.ModelType;
_allowMultiple = typeof(string) != realModelType &&
typeof(IEnumerable).IsAssignableFrom(realModelType);
- _currentValues = Generator.GetCurrentValues(
- ViewContext,
- For.ModelExplorer,
- expression: For.Name,
- allowMultiple: _allowMultiple);
+ _currentValues = Generator.GetCurrentValues(ViewContext, For.ModelExplorer, For.Name, _allowMultiple);
// Whether or not (not being highly unlikely) we generate anything, could update contained
// elements. Provide selected values for tag helpers.
@@ -115,6 +120,13 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
throw new ArgumentNullException(nameof(output));
}
+ // Pass through attribute that is also a well-known HTML attribute. Must be done prior to any copying
+ // from a TagBuilder.
+ if (Name != null)
+ {
+ output.CopyHtmlAttribute(nameof(Name), context);
+ }
+
// Ensure GenerateSelect() _never_ looks anything up in ViewData.
var items = Items ?? Enumerable.Empty();
@@ -125,6 +137,18 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
return;
}
+ // Ensure Generator does not throw due to empty "fullName" if user provided a name attribute.
+ IDictionary htmlAttributes = null;
+ if (string.IsNullOrEmpty(For.Name) &&
+ string.IsNullOrEmpty(ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix) &&
+ !string.IsNullOrEmpty(Name))
+ {
+ htmlAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase)
+ {
+ { "name", Name },
+ };
+ }
+
var tagBuilder = Generator.GenerateSelect(
ViewContext,
For.ModelExplorer,
@@ -133,7 +157,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
selectList: items,
currentValues: _currentValues,
allowMultiple: _allowMultiple,
- htmlAttributes: null);
+ htmlAttributes: htmlAttributes);
if (tagBuilder != null)
{
@@ -145,4 +169,4 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/TextAreaTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/TextAreaTagHelper.cs
index bf04f35d3a..293b60a05a 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/TextAreaTagHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/TextAreaTagHelper.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
@@ -40,6 +41,15 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(ForAttributeName)]
public ModelExpression For { get; set; }
+ ///
+ /// The name of the <input> element.
+ ///
+ ///
+ /// Passed through to the generated HTML in all cases. Also used to determine whether is
+ /// valid with an empty .
+ ///
+ public string Name { get; set; }
+
///
/// Does nothing if is null.
public override void Process(TagHelperContext context, TagHelperOutput output)
@@ -54,13 +64,32 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
throw new ArgumentNullException(nameof(output));
}
+ // Pass through attribute that is also a well-known HTML attribute. Must be done prior to any copying
+ // from a TagBuilder.
+ if (Name != null)
+ {
+ output.CopyHtmlAttribute(nameof(Name), context);
+ }
+
+ // Ensure Generator does not throw due to empty "fullName" if user provided a name attribute.
+ IDictionary htmlAttributes = null;
+ if (string.IsNullOrEmpty(For.Name) &&
+ string.IsNullOrEmpty(ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix) &&
+ !string.IsNullOrEmpty(Name))
+ {
+ htmlAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase)
+ {
+ { "name", Name },
+ };
+ }
+
var tagBuilder = Generator.GenerateTextArea(
ViewContext,
For.ModelExplorer,
For.Name,
rows: 0,
columns: 0,
- htmlAttributes: null);
+ htmlAttributes: htmlAttributes);
if (tagBuilder != null)
{
diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/ValidationMessageTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/ValidationMessageTagHelper.cs
index 80820f6894..8858623013 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/ValidationMessageTagHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/ValidationMessageTagHelper.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
@@ -16,6 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlTargetElement("span", Attributes = ValidationForAttributeName)]
public class ValidationMessageTagHelper : TagHelper
{
+ private const string DataValidationForAttributeName = "data-valmsg-for";
private const string ValidationForAttributeName = "asp-validation-for";
///
@@ -36,9 +38,6 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
protected IHtmlGenerator Generator { get; }
- ///
- /// Name to be validated on the current model.
- ///
[HtmlAttributeName(ValidationForAttributeName)]
public ModelExpression For { get; set; }
@@ -58,13 +57,27 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
if (For != null)
{
+ // Ensure Generator does not throw due to empty "fullName" if user provided data-valmsg-for attribute.
+ // Assume data-valmsg-for value is non-empty if attribute is present at all. Should align with name of
+ // another tag helper e.g. an and those tag helpers bind Name.
+ IDictionary htmlAttributes = null;
+ if (string.IsNullOrEmpty(For.Name) &&
+ string.IsNullOrEmpty(ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix) &&
+ output.Attributes.ContainsName(DataValidationForAttributeName))
+ {
+ htmlAttributes = new Dictionary(StringComparer.OrdinalIgnoreCase)
+ {
+ { DataValidationForAttributeName, "-non-empty-value-" },
+ };
+ }
+
var tagBuilder = Generator.GenerateValidationMessage(
ViewContext,
For.ModelExplorer,
For.Name,
message: null,
tag: null,
- htmlAttributes: null);
+ htmlAttributes: htmlAttributes);
if (tagBuilder != null)
{
diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/DefaultHtmlGenerator.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/DefaultHtmlGenerator.cs
index 0b9a75e282..e502341da4 100644
--- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/DefaultHtmlGenerator.cs
+++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/DefaultHtmlGenerator.cs
@@ -214,8 +214,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
if (modelExplorer.Model != null)
{
- bool modelChecked;
- if (bool.TryParse(modelExplorer.Model.ToString(), out modelChecked))
+ if (bool.TryParse(modelExplorer.Model.ToString(), out var modelChecked))
{
isChecked = modelChecked;
}
@@ -261,7 +260,10 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
tagBuilder.TagRenderMode = TagRenderMode.SelfClosing;
var fullName = NameAndIdProvider.GetFullHtmlFieldName(viewContext, expression);
- tagBuilder.MergeAttribute("name", fullName);
+ if (!string.IsNullOrEmpty(fullName))
+ {
+ tagBuilder.MergeAttribute("name", fullName);
+ }
return tagBuilder;
}
@@ -363,8 +365,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
}
// Special-case opaque values and arbitrary binary data.
- var byteArrayValue = value as byte[];
- if (byteArrayValue != null)
+ if (value is byte[] byteArrayValue)
{
value = Convert.ToBase64String(byteArrayValue);
}
@@ -596,7 +597,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
}
var fullName = NameAndIdProvider.GetFullHtmlFieldName(viewContext, expression);
- if (string.IsNullOrEmpty(fullName))
+ var htmlAttributeDictionary = GetHtmlAttributeDictionaryOrNull(htmlAttributes);
+ if (!IsFullNameValid(fullName, htmlAttributeDictionary))
{
throw new ArgumentException(
Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty(
@@ -622,17 +624,20 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
var tagBuilder = new TagBuilder("select");
tagBuilder.InnerHtml.SetHtmlContent(listItemBuilder);
- tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
- tagBuilder.MergeAttribute("name", fullName, true /* replaceExisting */);
+ tagBuilder.MergeAttributes(htmlAttributeDictionary);
NameAndIdProvider.GenerateId(viewContext, tagBuilder, fullName, IdAttributeDotReplacement);
+ if (!string.IsNullOrEmpty(fullName))
+ {
+ tagBuilder.MergeAttribute("name", fullName, replaceExisting: true);
+ }
+
if (allowMultiple)
{
tagBuilder.MergeAttribute("multiple", "multiple");
}
// If there are any errors for a named field, we add the css attribute.
- ModelStateEntry entry;
- if (viewContext.ViewData.ModelState.TryGetValue(fullName, out entry))
+ if (viewContext.ViewData.ModelState.TryGetValue(fullName, out var entry))
{
if (entry.Errors.Count > 0)
{
@@ -672,7 +677,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
}
var fullName = NameAndIdProvider.GetFullHtmlFieldName(viewContext, expression);
- if (string.IsNullOrEmpty(fullName))
+ var htmlAttributeDictionary = GetHtmlAttributeDictionaryOrNull(htmlAttributes);
+ if (!IsFullNameValid(fullName, htmlAttributeDictionary))
{
throw new ArgumentException(
Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty(
@@ -684,8 +690,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
nameof(expression));
}
- ModelStateEntry entry;
- viewContext.ViewData.ModelState.TryGetValue(fullName, out entry);
+ viewContext.ViewData.ModelState.TryGetValue(fullName, out var entry);
var value = string.Empty;
if (entry != null && entry.AttemptedValue != null)
@@ -699,18 +704,24 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
var tagBuilder = new TagBuilder("textarea");
NameAndIdProvider.GenerateId(viewContext, tagBuilder, fullName, IdAttributeDotReplacement);
- tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes), true);
+ tagBuilder.MergeAttributes(htmlAttributeDictionary, replaceExisting: true);
if (rows > 0)
{
- tagBuilder.MergeAttribute("rows", rows.ToString(CultureInfo.InvariantCulture), true);
+ tagBuilder.MergeAttribute("rows", rows.ToString(CultureInfo.InvariantCulture), replaceExisting: true);
}
if (columns > 0)
{
- tagBuilder.MergeAttribute("cols", columns.ToString(CultureInfo.InvariantCulture), true);
+ tagBuilder.MergeAttribute(
+ "cols",
+ columns.ToString(CultureInfo.InvariantCulture),
+ replaceExisting: true);
}
- tagBuilder.MergeAttribute("name", fullName, true);
+ if (!string.IsNullOrEmpty(fullName))
+ {
+ tagBuilder.MergeAttribute("name", fullName, replaceExisting: true);
+ }
AddPlaceholderAttribute(viewContext.ViewData, tagBuilder, modelExplorer, expression);
AddValidationAttributes(viewContext, tagBuilder, modelExplorer, expression);
@@ -773,7 +784,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
}
var fullName = NameAndIdProvider.GetFullHtmlFieldName(viewContext, expression);
- if (string.IsNullOrEmpty(fullName))
+ var htmlAttributeDictionary = GetHtmlAttributeDictionaryOrNull(htmlAttributes);
+ if (!IsFullNameValid(fullName, htmlAttributeDictionary, fallbackAttributeName: "data-valmsg-for"))
{
throw new ArgumentException(
Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty(
@@ -791,8 +803,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
return null;
}
- ModelStateEntry entry;
- var tryGetModelStateResult = viewContext.ViewData.ModelState.TryGetValue(fullName, out entry);
+ var tryGetModelStateResult = viewContext.ViewData.ModelState.TryGetValue(fullName, out var entry);
var modelErrors = tryGetModelStateResult ? entry.Errors : null;
ModelError modelError = null;
@@ -812,8 +823,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
{
tag = viewContext.ValidationMessageElement;
}
+
var tagBuilder = new TagBuilder(tag);
- tagBuilder.MergeAttributes(GetHtmlAttributeDictionaryOrNull(htmlAttributes));
+ tagBuilder.MergeAttributes(htmlAttributeDictionary);
// Only the style of the span is changed according to the errors if message is null or empty.
// Otherwise the content and style is handled by the client-side validation.
@@ -838,7 +850,10 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
if (formContext != null)
{
- tagBuilder.MergeAttribute("data-valmsg-for", fullName);
+ if (!string.IsNullOrEmpty(fullName))
+ {
+ tagBuilder.MergeAttribute("data-valmsg-for", fullName);
+ }
var replaceValidationMessageContents = string.IsNullOrEmpty(message);
tagBuilder.MergeAttribute("data-valmsg-replace",
@@ -868,9 +883,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
return null;
}
- ModelStateEntry entryForModel;
if (excludePropertyErrors &&
- (!viewData.ModelState.TryGetValue(viewData.TemplateInfo.HtmlFieldPrefix, out entryForModel) ||
+ (!viewData.ModelState.TryGetValue(viewData.TemplateInfo.HtmlFieldPrefix, out var entryForModel) ||
entryForModel.Errors.Count == 0))
{
// Client-side validation (if enabled) will not affect the generated element and element will be empty.
@@ -964,18 +978,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
}
var fullName = NameAndIdProvider.GetFullHtmlFieldName(viewContext, expression);
- if (string.IsNullOrEmpty(fullName))
- {
- throw new ArgumentException(
- Resources.FormatHtmlGenerator_FieldNameCannotBeNullOrEmpty(
- typeof(IHtmlHelper).FullName,
- nameof(IHtmlHelper.Editor),
- typeof(IHtmlHelper<>).FullName,
- nameof(IHtmlHelper