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

SZL*_*SZL 3 c# asp.net asp.net-core-tag-helpers asp.net-core-2.2

我尝试扩展内置的 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";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,当我在 [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' 标签。

请帮我解决这个问题!谢谢!

Sha*_*hab 5

您可以从默认的继承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
Run Code Online (Sandbox Code Playgroud)

继承的例子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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)