Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
[Fixes #4013] Added support for areas in 'a' and 'form' tag helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
javiercn committed Feb 6, 2016
1 parent 477e620 commit 983f5b6
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@*
For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*@
@{
}

<a asp-action="Index" asp-controller="Home" asp-area="">Go home!</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
17 changes: 17 additions & 0 deletions samples/TagHelperSample.Web/Controllers/AdminController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace TagHelperSample.Web.Controllers
{
[Area("Admin")]
public class AdminController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
10 changes: 10 additions & 0 deletions samples/TagHelperSample.Web/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ public IActionResult Create()
return View();
}

// GET: /Home/Create
public IActionResult Link()
{
var pageLink = Url.Action("Index", new { page = (string)null });
var otherPageLink = Url.Action("Index", new { page = (string)"1" });
var yetAnotherPageLink = Url.Action("Index", new { page = "" });
return View();
}


// POST: Home/Create
[HttpPost]
public IActionResult Create(User user)
Expand Down
15 changes: 14 additions & 1 deletion samples/TagHelperSample.Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,20 @@ public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)

app.UseStaticFiles();

app.UseMvcWithDefaultRoute();
app.UseMvc(routes =>
{
routes.MapAreaRoute("Admin", "Admin", "Admin/{controller}/{action}", new
{
controller = "Admin",
action = "Index"
});

routes.MapRoute("Default", "{controller}/{action}", new
{
controller = "Home",
action = "Index"
});
});
}

public static void Main(string[] args)
Expand Down
1 change: 1 addition & 0 deletions samples/TagHelperSample.Web/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<script>bar();</script>

<h2>Index</h2>
<a asp-action="Index" asp-Controller="Admin" asp-area="Admin" asp-route-area="Yolo">Go to admin!</a>
@if (Model != null && Model.Count() != 0)
{
<div class="form-horizontal">
Expand Down
23 changes: 23 additions & 0 deletions src/Microsoft.AspNetCore.Mvc.TagHelpers/AnchorTagHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
/// </summary>
[HtmlTargetElement("a", Attributes = ActionAttributeName)]
[HtmlTargetElement("a", Attributes = ControllerAttributeName)]
[HtmlTargetElement("a", Attributes = AreaAttributeName)]
[HtmlTargetElement("a", Attributes = FragmentAttributeName)]
[HtmlTargetElement("a", Attributes = HostAttributeName)]
[HtmlTargetElement("a", Attributes = ProtocolAttributeName)]
Expand All @@ -24,6 +25,7 @@ public class AnchorTagHelper : TagHelper
{
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";
Expand Down Expand Up @@ -67,6 +69,13 @@ public override int Order
[HtmlAttributeName(ControllerAttributeName)]
public string Controller { get; set; }

/// <summary>
/// The name of the area.
/// </summary>
/// <remarks>Must be <c>null</c> if <see cref="Route"/> is non-<c>null</c>.</remarks>
[HtmlAttributeName(AreaAttributeName)]
public string Area { get; set; }

/// <summary>
/// The protocol for the URL, such as &quot;http&quot; or &quot;https&quot;.
/// </summary>
Expand Down Expand Up @@ -147,6 +156,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (Action != null ||
Controller != null ||
Area != null ||
Route != null ||
Protocol != null ||
Host != null ||
Expand All @@ -159,6 +169,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
"<a>",
ActionAttributeName,
ControllerAttributeName,
AreaAttributeName,
RouteAttributeName,
ProtocolAttributeName,
HostAttributeName,
Expand All @@ -180,6 +191,18 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
}
}

if (Area != null)
{
if (routeValues == null)
{
routeValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
}

// If a user specifies asp-area and asp-route-area we want the first one to always win
// so we unconditionally replace the value in the dictionary with that one.
routeValues["area"] = Area;
}

TagBuilder tagBuilder;
if (Route == null)
{
Expand Down
23 changes: 22 additions & 1 deletion src/Microsoft.AspNetCore.Mvc.TagHelpers/FormTagHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers
/// </summary>
[HtmlTargetElement("form", Attributes = ActionAttributeName)]
[HtmlTargetElement("form", Attributes = AntiforgeryAttributeName)]
[HtmlTargetElement("form", Attributes = AreaAttributeName)]
[HtmlTargetElement("form", Attributes = ControllerAttributeName)]
[HtmlTargetElement("form", Attributes = RouteAttributeName)]
[HtmlTargetElement("form", Attributes = RouteValuesDictionaryName)]
Expand All @@ -23,6 +24,7 @@ public class FormTagHelper : TagHelper
{
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";
Expand Down Expand Up @@ -66,6 +68,12 @@ public override int Order
[HtmlAttributeName(ControllerAttributeName)]
public string Controller { get; set; }

/// <summary>
/// The name of the area.
/// </summary>
[HtmlAttributeName(AreaAttributeName)]
public string Area { get; set; }

/// <summary>
/// Whether the antiforgery token should be generated.
/// </summary>
Expand Down Expand Up @@ -141,7 +149,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
// If "action" is already set, it means the user is attempting to use a normal <form>.
if (output.Attributes.ContainsName(HtmlActionAttributeName))
{
if (Action != null || Controller != null || Route != null || RouteValues.Count != 0)
if (Action != null || Controller != null || Area != null || Route != null || RouteValues.Count != 0)
{
// User also specified bound attributes we cannot use.
throw new InvalidOperationException(
Expand All @@ -150,6 +158,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
HtmlActionAttributeName,
ActionAttributeName,
ControllerAttributeName,
AreaAttributeName,
RouteAttributeName,
RouteValuesPrefix));
}
Expand All @@ -171,6 +180,18 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
}
}

if (Area != null)
{
if (routeValues == null)
{
routeValues = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
}

// If a user specifies asp-area and asp-route-area we want the first one to always win
// so we unconditionally replace the value in the dictionary with that one.
routeValues["area"] = Area;
}

TagBuilder tagBuilder;
if (Route == null)
{
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/Microsoft.AspNetCore.Mvc.TagHelpers/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@
<value>Cannot determine an '{4}' attribute for {0}. An {0} with a specified '{1}' must not have an '{2}' or '{3}' attribute.</value>
</data>
<data name="AnchorTagHelper_CannotOverrideHref" xml:space="preserve">
<value>Cannot override the '{8}' attribute for {0}. An {0} with a specified '{8}' must not have attributes starting with '{7}' or an '{1}', '{2}', '{3}', '{4}', '{5}', or '{6}' attribute.</value>
<value>Cannot override the '{9}' attribute for {0}. An {0} with a specified '{9}' must not have attributes starting with '{8}' or an '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', or '{7}' attribute.</value>
</data>
<data name="FormTagHelper_CannotOverrideAction" xml:space="preserve">
<value>Cannot override the '{1}' attribute for {0}. A {0} with a specified '{1}' must not have attributes starting with '{5}' or an '{2}' or '{3}' or '{4}' attribute.</value>
<value>Cannot override the '{1}' attribute for {0}. A {0} with a specified '{1}' must not have attributes starting with '{6}' or an '{2}' or '{3}' or '{4}' or '{5}' attribute.</value>
</data>
<data name="InputTagHelper_InvalidExpressionResult" xml:space="preserve">
<value>Unexpected '{1}' expression result type '{2}' for {0}. '{1}' must be of type '{3}' if '{4}' is '{5}'.</value>
Expand Down

0 comments on commit 983f5b6

Please sign in to comment.