在ASP Net.Core 2.2中使用自动属性扩展AnchorTagHelper

时间:2019-02-18 14:09:39

标签: c# asp.net asp.net-core-2.2 asp.net-core-tag-helpers

我尝试扩展内置的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”标签。

请帮助我解决此问题!谢谢!

2 个答案:

答案 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);
        }
    }
}