diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs index d4d7787952..8ef8ae97c6 100644 --- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs +++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs @@ -162,7 +162,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers Protocol != null || Host != null || Fragment != null || - RouteValues.Count != 0) + (_routeValues != null && _routeValues.Count > 0)) { // User specified an href and one of the bound attributes; can't determine the href attribute. throw new InvalidOperationException( @@ -194,7 +194,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers routeValues = new RouteValueDictionary(); } - // Unconditionally replace any value from asp-route-area. + // Unconditionally replace any value from asp-route-area. routeValues["area"] = Area; } diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/ButtonTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/FormActionTagHelper.cs similarity index 63% rename from src/Microsoft.AspNetCore.Mvc.TagHelpers/ButtonTagHelper.cs rename to src/Microsoft.AspNetCore.Mvc.TagHelpers/FormActionTagHelper.cs index 7fc14aead7..4c4ba9c8d0 100644 --- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/ButtonTagHelper.cs +++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/FormActionTagHelper.cs @@ -12,7 +12,8 @@ using Microsoft.AspNetCore.Routing; namespace Microsoft.AspNetCore.Mvc.TagHelpers { /// - /// implementation targeting <button> elements. + /// implementation targeting <button> elements and <input> elements with + /// their type attribute set to image or submit. /// [HtmlTargetElement("button", Attributes = ActionAttributeName)] [HtmlTargetElement("button", Attributes = ControllerAttributeName)] @@ -20,22 +21,51 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers [HtmlTargetElement("button", Attributes = RouteAttributeName)] [HtmlTargetElement("button", Attributes = RouteValuesDictionaryName)] [HtmlTargetElement("button", Attributes = RouteValuesPrefix + "*")] - public class ButtonTagHelper : TagHelper + [HtmlTargetElement("input", Attributes = ImageActionAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = ImageControllerAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = ImageAreaAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = ImageRouteAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = ImageRouteValuesDictionarySelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = ImageRouteValuesSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = SubmitActionAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = SubmitControllerAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = SubmitAreaAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = SubmitRouteAttributeSelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = SubmitRouteValuesDictionarySelector, TagStructure = TagStructure.WithoutEndTag)] + [HtmlTargetElement("input", Attributes = SubmitRouteValuesSelector, TagStructure = TagStructure.WithoutEndTag)] + public class FormActionTagHelper : TagHelper { private const string ActionAttributeName = "asp-action"; - private const string ControllerAttributeName = "asp-controller"; private const string AreaAttributeName = "asp-area"; + private const string ControllerAttributeName = "asp-controller"; private const string RouteAttributeName = "asp-route"; private const string RouteValuesDictionaryName = "asp-all-route-data"; private const string RouteValuesPrefix = "asp-route-"; private const string FormAction = "formaction"; + + private const string ImageTypeSelector = "[type=image], "; + private const string ImageActionAttributeSelector = ImageTypeSelector + ActionAttributeName; + private const string ImageAreaAttributeSelector = ImageTypeSelector + AreaAttributeName; + private const string ImageControllerAttributeSelector = ImageTypeSelector + ControllerAttributeName; + private const string ImageRouteAttributeSelector = ImageTypeSelector + RouteAttributeName; + private const string ImageRouteValuesDictionarySelector = ImageTypeSelector + RouteValuesDictionaryName; + private const string ImageRouteValuesSelector = ImageTypeSelector + RouteValuesPrefix + "*"; + + private const string SubmitTypeSelector = "[type=submit], "; + private const string SubmitActionAttributeSelector = SubmitTypeSelector + ActionAttributeName; + private const string SubmitAreaAttributeSelector = SubmitTypeSelector + AreaAttributeName; + private const string SubmitControllerAttributeSelector = SubmitTypeSelector + ControllerAttributeName; + private const string SubmitRouteAttributeSelector = SubmitTypeSelector + RouteAttributeName; + private const string SubmitRouteValuesDictionarySelector = SubmitTypeSelector + RouteValuesDictionaryName; + private const string SubmitRouteValuesSelector = SubmitTypeSelector + RouteValuesPrefix + "*"; + private IDictionary _routeValues; /// - /// Creates a new . + /// Creates a new . /// /// The . - public ButtonTagHelper(IUrlHelperFactory urlHelperFactory) + public FormActionTagHelper(IUrlHelperFactory urlHelperFactory) { UrlHelperFactory = urlHelperFactory; } @@ -120,15 +150,20 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers throw new ArgumentNullException(nameof(output)); } - // If "formaction" is already set, it means the user is attempting to use a normal button. + // If "formaction" is already set, it means the user is attempting to use a normal button or input element. if (output.Attributes.ContainsName(FormAction)) { - if (Action != null || Controller != null || Area != null || Route != null || RouteValues.Count != 0) + if (Action != null || + Controller != null || + Area != null || + Route != null || + (_routeValues != null && _routeValues.Count > 0)) { - // User specified a formaction and one of the bound attributes; can't determine the formaction attribute. + // User specified a formaction and one of the bound attributes; can't override that formaction + // attribute. throw new InvalidOperationException( - Resources.FormatButtonTagHelper_CannotOverrideFormAction( - "