diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs
index 612e76e1b6..1dd7a2583d 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs
@@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
///
[HtmlTargetElement("a", Attributes = ActionAttributeName)]
[HtmlTargetElement("a", Attributes = ControllerAttributeName)]
+ [HtmlTargetElement("a", Attributes = AreaAttributeName)]
[HtmlTargetElement("a", Attributes = FragmentAttributeName)]
[HtmlTargetElement("a", Attributes = HostAttributeName)]
[HtmlTargetElement("a", Attributes = ProtocolAttributeName)]
@@ -24,6 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
{
private const string ActionAttributeName = "asp-action";
private const string ControllerAttributeName = "asp-controller";
+ private const string AreaAttributeName = "asp-area";
private const string FragmentAttributeName = "asp-fragment";
private const string HostAttributeName = "asp-host";
private const string ProtocolAttributeName = "asp-protocol";
@@ -67,6 +69,13 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(ControllerAttributeName)]
public string Controller { get; set; }
+ ///
+ /// The name of the area.
+ ///
+ /// Must be null if is non-null.
+ [HtmlAttributeName(AreaAttributeName)]
+ public string Area { get; set; }
+
///
/// The protocol for the URL, such as "http" or "https".
///
@@ -147,6 +156,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
{
if (Action != null ||
Controller != null ||
+ Area != null ||
Route != null ||
Protocol != null ||
Host != null ||
@@ -159,6 +169,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
"",
ActionAttributeName,
ControllerAttributeName,
+ AreaAttributeName,
RouteAttributeName,
ProtocolAttributeName,
HostAttributeName,
@@ -180,6 +191,17 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
}
}
+ if (Area != null)
+ {
+ if (routeValues == null)
+ {
+ routeValues = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ }
+
+ // Unconditionally replace any value from asp-route-area.
+ routeValues["area"] = Area;
+ }
+
TagBuilder tagBuilder;
if (Route == null)
{
diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/FormTagHelper.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/FormTagHelper.cs
index 922f5ebaa8..029f6d72e1 100644
--- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/FormTagHelper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/FormTagHelper.cs
@@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
///
[HtmlTargetElement("form", Attributes = ActionAttributeName)]
[HtmlTargetElement("form", Attributes = AntiforgeryAttributeName)]
+ [HtmlTargetElement("form", Attributes = AreaAttributeName)]
[HtmlTargetElement("form", Attributes = ControllerAttributeName)]
[HtmlTargetElement("form", Attributes = RouteAttributeName)]
[HtmlTargetElement("form", Attributes = RouteValuesDictionaryName)]
@@ -23,6 +24,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
{
private const string ActionAttributeName = "asp-action";
private const string AntiforgeryAttributeName = "asp-antiforgery";
+ 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";
@@ -66,6 +68,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
[HtmlAttributeName(ControllerAttributeName)]
public string Controller { get; set; }
+ ///
+ /// The name of the area.
+ ///
+ [HtmlAttributeName(AreaAttributeName)]
+ public string Area { get; set; }
+
///
/// Whether the antiforgery token should be generated.
///
@@ -141,7 +149,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
// If "action" is already set, it means the user is attempting to use a normal