我尝试扩展内置的AnchorTagHelper对象,以将与文化相关的设置自动添加到生成的url中。
我的代码:
namespace MyCoreSite.Mvc.TagHelpers
{
[HtmlTargetElement("a")]
public class MyAnchorTagHelper : AnchorTagHelper
{
public MyAnchorTagHelper(IHtmlGenerator generator) : base(generator)
{
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var requestCulture = this.ViewContext.HttpContext.Features.Get<IRequestCultureFeature>();
if (context.AllAttributes["asp-route-culture"] == null)
{
this.RouteValues.Add("culture", requestCulture.RequestCulture.UICulture.Name);
}
base.Process(context, output);
output.TagName = "a";
}
}
}
问题是,当我在[HtmlTargetElement(“ a”)]属性中使用默认的'a'标签名称时,会引发此异常:
System.InvalidOperationException:'无法覆盖'href' 的属性。具有指定“ href”的不得包含 以“ asp-route-”或“ asp-action”开头的属性, 'asp-controller','asp-area','asp-route','asp-protocol','asp-host', “ asp-fragment”,“ asp-page”或“ asp-page-handler”属性。
如果我使用另一个标签名称代替“ a”(例如“ aa”),那么它会起作用,但是我想在视图中使用“ a”标签。
请帮助我解决此问题!谢谢!
答案 0 :(得分:0)
每个标记帮助程序都按顺序独立运行,因此除非完全删除了标记帮助程序库,否则无法真正覆盖AnchorTagHelper
之类的默认标记帮助程序(删除在_ViewImports.cshtml
中带入标记的行)。否则,这里实际发生的是默认的AchorTagHelper
处理标签,然后您的自定义MyAnchorTagHelper
处理已修改的标签。如果从内置的标记帮助程序继承,则实际上可能会引起问题,前提是它们依赖于之前或之后出现的特定属性。
对于您的特定情况,最好的选择是不要继承自AnchorTagHelper
,而只是修改href
的属性,该属性将首先由AnchorTagHelper
处理标签而产生。只需确保_ViewImports.cshtml
中的默认标记之后就包含了标记帮助程序库,因为操作顺序很重要。
答案 1 :(得分:0)
您可以从默认的AnchorTagHelper
继承,重写Process
方法,然后在Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper
文件中删除原始的_ViewImports.cshtml
。使用这种方法,您的页面上只会有一个AnchorTagHelper
。
示例_ViewImports.cshtml
:
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, YourProject.PlatformExtensions
示例继承了AnchorTagHelper
:
namespace YourProject.PlatformExtensions.TagHelpers
{
public static class AnchorTagHelperSettings
{
public static string DefaultCulture = "en";
}
[HtmlTargetElement("a", Attributes = ActionAttributeName)]
[HtmlTargetElement("a", Attributes = ControllerAttributeName)]
[HtmlTargetElement("a", Attributes = AreaAttributeName)]
[HtmlTargetElement("a", Attributes = PageAttributeName)]
[HtmlTargetElement("a", Attributes = PageHandlerAttributeName)]
[HtmlTargetElement("a", Attributes = FragmentAttributeName)]
[HtmlTargetElement("a", Attributes = HostAttributeName)]
[HtmlTargetElement("a", Attributes = ProtocolAttributeName)]
[HtmlTargetElement("a", Attributes = RouteAttributeName)]
[HtmlTargetElement("a", Attributes = RouteValuesDictionaryName)]
[HtmlTargetElement("a", Attributes = RouteValuesPrefix + "*")]
public class AnchorTagHelper : Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper
{
private const string ActionAttributeName = "asp-action";
private const string ControllerAttributeName = "asp-controller";
private const string AreaAttributeName = "asp-area";
private const string PageAttributeName = "asp-page";
private const string PageHandlerAttributeName = "asp-page-handler";
private const string FragmentAttributeName = "asp-fragment";
private const string HostAttributeName = "asp-host";
private const string ProtocolAttributeName = "asp-protocol";
private const string RouteAttributeName = "asp-route";
private const string RouteValuesDictionaryName = "asp-all-route-data";
private const string RouteValuesPrefix = "asp-route-";
private const string Href = "href"; public override int Order => base.Order;
/// <summary>
/// Creates a new <see cref="AnchorTagHelper"/>.
/// </summary>
/// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
public AnchorTagHelper(IHtmlGenerator generator) : base(generator)
{
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (!output.Attributes.ContainsName(Href) &&
!context.AllAttributes.ContainsName("asp-route-lang") &&
!(RouteValues?.ContainsKey("lang") == true))
{
var routeValues = ViewContext?.RouteData?.Values;
if (routeValues != null)
{
var langValue = routeValues["lang"]?.ToString();
if (string.IsNullOrWhiteSpace(langValue))
{
langValue = AnchorTagHelperSettings.DefaultCulture;
}
if (RouteValues == null)
{
RouteValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
RouteValues.Add("lang", langValue);
}
}
base.Process(context, output);
}
}
}