This repository has been archived by the owner on Dec 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added a TagHelper that targets the <a> tag and allows users to do the equivalent of Html.ActionLink or Html.RouteLink. #1247
- Loading branch information
1 parent
14cf681
commit eb55199
Showing
3 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Linq; | ||
using Microsoft.AspNet.Mvc.Rendering; | ||
using Microsoft.AspNet.Mvc.TagHelpers.Internal; | ||
using Microsoft.AspNet.Razor.Runtime.TagHelpers; | ||
|
||
namespace Microsoft.AspNet.Mvc.TagHelpers | ||
{ | ||
/// <summary> | ||
/// <see cref="ITagHelper"/> implementation targeting <a> elements. | ||
/// </summary> | ||
[TagName("a")] | ||
public class AnchorTagHelper : TagHelper | ||
{ | ||
private const string RouteAttributePrefix = "route-"; | ||
|
||
[Activate] | ||
private ViewContext ViewContext { get; set; } | ||
|
||
[Activate] | ||
private IHtmlGenerator Generator { get; set; } | ||
|
||
/// <summary> | ||
/// The name of the action method. | ||
/// </summary> | ||
/// <remarks>Cannot be provided if <see cref="Route"/> is specified.</remarks> | ||
public string Action { get; set; } | ||
|
||
/// <summary> | ||
/// The name of the controller. | ||
/// </summary> | ||
/// <remarks>Cannot be provided if <see cref="Route"/> is specified.</remarks> | ||
public string Controller { get; set; } | ||
|
||
/// <summary> | ||
/// The protocol for the URL, such as "http" or "https". | ||
/// </summary> | ||
public string Protocol { get; set; } | ||
|
||
/// <summary> | ||
/// The host name for the URL. | ||
/// </summary> | ||
public string Host { get; set; } | ||
|
||
/// <summary> | ||
/// The URL fragment name (the anchor name). | ||
/// </summary> | ||
public string Fragment { get; set; } | ||
|
||
/// <summary> | ||
/// Name of the route. | ||
/// </summary> | ||
/// <remarks>Cannot be provided if <see cref="Action"/> or <see cref="Controller"/> is specified.</remarks> | ||
public string Route { get; set; } | ||
|
||
/// <inheritdoc /> | ||
/// <remarks>Does nothing if user provides a "href" attribute. Cannot specify a "href" attribute AND | ||
/// <see cref="Action"/>, <see cref="Controller"/> or <see cref="Route"/>.</remarks> | ||
public override void Process(TagHelperContext context, TagHelperOutput output) | ||
{ | ||
// If there's an "href" on the tag it means it's being used as a normal anchor. | ||
if (output.Attributes.ContainsKey("href")) | ||
{ | ||
if (Action != null || Controller != null || Route != null) | ||
{ | ||
// User specified an href AND a Action, Controller or Route; can't determine the href attribute. | ||
throw new InvalidOperationException( | ||
Resources.FormatAnchorTagHelper_CannotDetermineHrefOneSpecified( | ||
nameof(AnchorTagHelper), | ||
nameof(Action), | ||
nameof(Controller), | ||
nameof(Route))); | ||
} | ||
|
||
// User is using the AnchorTagHelper as normal anchor tag, restore any provided attributes. | ||
RestoreBoundHtmlAttributes(context, output); | ||
} | ||
else | ||
{ | ||
TagBuilder tagBuilder; | ||
|
||
var prefixedValues = TagHelperOutputHelper.PullPrefixedAttributes(RouteAttributePrefix, output); | ||
|
||
// Generator.GenerateActionLink || GenerateRouteLink does not accept a Dictionary<string, string> for | ||
// route values. | ||
var routeValues = prefixedValues.ToDictionary( | ||
attribute => attribute.Key.Substring(RouteAttributePrefix.Length), | ||
attribute => (object)attribute.Value); | ||
|
||
if (Route == null) | ||
{ | ||
tagBuilder = Generator.GenerateActionLink(linkText: string.Empty, | ||
actionName: Action, | ||
controllerName: Controller, | ||
protocol: Protocol, | ||
hostname: Host, | ||
fragment: Fragment, | ||
routeValues: routeValues, | ||
htmlAttributes: null); | ||
} | ||
else if (Action != null || Controller != null) | ||
{ | ||
// Route and Action or Controller were specified. Can't determine the href attribute. | ||
throw new InvalidOperationException( | ||
Resources.FormatAnchorTagHelper_CannotDetermineHrefRouteActionOrControllerSpecified( | ||
nameof(AnchorTagHelper), | ||
nameof(Route), | ||
nameof(Action), | ||
nameof(Controller))); | ||
} | ||
else | ||
{ | ||
tagBuilder = Generator.GenerateRouteLink(linkText: string.Empty, | ||
routeName: Route, | ||
protocol: Protocol, | ||
hostName: Host, | ||
fragment: Fragment, | ||
routeValues: routeValues, | ||
htmlAttributes: null); | ||
} | ||
|
||
TagHelperOutputHelper.MergeAttributes(tagBuilder, output); | ||
} | ||
} | ||
|
||
private void RestoreBoundHtmlAttributes(TagHelperContext context, TagHelperOutput output) | ||
{ | ||
if (Action != null) | ||
{ | ||
TagHelperOutputHelper.RestoreBoundHtmlAttribute(nameof(Action), context, output); | ||
} | ||
|
||
if (Controller != null) | ||
{ | ||
TagHelperOutputHelper.RestoreBoundHtmlAttribute(nameof(Controller), context, output); | ||
} | ||
|
||
if (Protocol != null) | ||
{ | ||
TagHelperOutputHelper.RestoreBoundHtmlAttribute(nameof(Protocol), context, output); | ||
} | ||
|
||
if (Host != null) | ||
{ | ||
TagHelperOutputHelper.RestoreBoundHtmlAttribute(nameof(Host), context, output); | ||
} | ||
|
||
if (Fragment != null) | ||
{ | ||
TagHelperOutputHelper.RestoreBoundHtmlAttribute(nameof(Fragment), context, output); | ||
} | ||
|
||
if (Route != null) | ||
{ | ||
TagHelperOutputHelper.RestoreBoundHtmlAttribute(nameof(Route), context, output); | ||
} | ||
} | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
src/Microsoft.AspNet.Mvc.TagHelpers/Properties/Resources.Designer.cs
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters