我可以将“Tag Helper”用于返回HTML的自定义“Tag Helper”中吗?

29

最近我遇到了一个情况,我想在标签助手中使用另一个标签助手。 我搜索了一下,但找不到其他人尝试这样做,我是在使用不良惯例还是错过了文档?

例如:标签助手A输出包含另一个标签助手的HTML。

例如:

[HtmlTargetElement("tag-name")]
public class RazorTagHelper : TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("<a asp-action=\"Home\" ");
        output.Content.SetHtmlContent(sb.ToString());
    }
}

我是否有办法从C#处理<a asp-action> </a>标签助手?或者用标签助手重新处理输出HTML?


这个有用吗?https://dev59.com/o1wY5IYBdhLWcg3wYW1X - Vlince
@Vlince 感谢提供链接,但那不是我想要做的,我想要一个单独的输入标签,没有其他嵌套标签。我真正想做的是从另一个标签助手调用一个标签助手。 - Jacob Linney
1
你是否在寻找视图组件 - Christian Gollhardt
1
视图组件可以适用于这种情况,但如果可能的话,我真的想保留标记助手的类似HTML的语法。 - Jacob Linney
1
从ASP.NET 2.1开始,一些类已经发生了变化。请参阅此问答:https://dev59.com/8rHma4cB1Zd3GeqPPbFh#54584218 - chakeda
3个回答

20

不,你不能这样做。TagHelpers是在Razor解析时使用的功能。

另一种方法是创建一个TagHelper并手动调用它的ProcessAsync/Process方法。例如:

var anchorTagHelper = new AnchorTagHelper
{
    Action = "Home",
};
var anchorOutput = new TagHelperOutput("a", new TagHelperAttributeList(), (useCachedResult, encoder) => new HtmlString());
var anchorContext = new TagHelperContext(
    new TagHelperAttributeList(new[] { new TagHelperAttribute("asp-action", new HtmlString("Home")) }),
    new Dictionary<object, object>(),
    Guid.NewGuid());
await anchorTagHelper.ProcessAsync(anchorContext, anchorOutput);
output.Content.SetHtmlContent(anchorOutput);

4
真是一团糟,如果这是唯一的方法,那就太不幸了。我会把这个问题保持开放状态一天左右,只是为了确认这确实是我必须这样做的方式。如果没有其他的答案,我肯定会接受它。谢谢。 - Jacob Linney
1
我认为这个答案非常好。对于所有高级功能,ViewComponents 是最佳选择。对于您的情况,直接使用 UrlHelper 可能更好 @JacobLinney - Christian Gollhardt
@ChristianGollhardt 谢谢您的意见和建议;我只是想确认没有更好的方法来做这件事。而且这不是我的实际用例,仅仅是一个抽象。 - Jacob Linney

7
如果有人想要重复使用asp.net core中内置的标签助手,可以使用IHtmlGenerator。对于其他类型的标签助手的重复使用,我还没有找到比@N. Taylor Mullen答案更简单的选项。
以下是如何重用asp-action标签助手的方法:
[HtmlTargetElement("helplink")]
public class RazorTagHelper : TagHelper
{
    private readonly IHtmlGenerator _htmlGenerator;

    public RazorTagHelper(IHtmlGenerator htmlGenerator)
    {
        _htmlGenerator = htmlGenerator;
    }

    [ViewContext]
    public ViewContext ViewContext { set; get; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "div";
        output.TagMode = TagMode.StartTagAndEndTag;
        var actionAnchor = _htmlGenerator.GenerateActionLink(
            ViewContext,
            linkText: "Home",
            actionName: "Index",
            controllerName: null,
            fragment: null,
            hostname: null,
            htmlAttributes: null,
            protocol: null,
            routeValues: null
            );
        var builder = new HtmlContentBuilder();
        builder.AppendHtml("Here's the link: ");
        builder.AppendHtml(actionAnchor);
        output.Content.SetHtmlContent(builder);
    }
}

6

我不知道这是否适用于您的情况,但可以继承 AnchorTagHelper 并像下面这样进行自定义。

public class TestTagHelper : AnchorTagHelper
{
    public TestTagHelper(IHtmlGenerator htmlGenerator) : base(htmlGenerator) { }

    public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        // Replaces <test> with <a> tag
        output.TagName = "a"; 
        // do custom processing
        output.Attributes.SetAttribute("class", "custom-class");
        // let the base class generate the href 
        // note the base method may override your changes so it may be  
        // preferable to call it first instead of last.
        await base.ProcessAsync(context, output);
    }
}

接下来您可以在视图中使用这个标签助手,利用内置的默认AnchorTagHelper所提供的所有优点。

<test asp-action="Index" asp-route-id="5"></test>

1
提醒一下,应该首先调用base.ProcessAsync,因为基础标签助手可以在调用之前轻松地覆盖您对输出所做的任何更改,例如使用SetHtmlContent()。一旦您调用了基础代码,就可以在已经存在的内容周围添加您的附加内容。 - raterus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接