ASP.NETのTagHelperからHTMLの文字列を取得する拡張メソッドを定義するには?
ASP.NETのTagHelperはとても便利ですが、TagHelperからHTMLを簡単に取得する方法がありません。そこでHTMLを取得する拡張メソッドを作ってみました。
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Text.Encodings.Web;
namespace HigLabo.Web;
public static class TagHelperExtensions
{
public static async ValueTask<string> WriteHtmlAsync(this TagHelper tagHelper)
{
using (var writer = new StringWriter())
{
await WriteToAsync(tagHelper, writer, HtmlEncoder.Default);
return writer.ToString();
}
}
public static ValueTask WriteToAsync(this TagHelper tagHelper, TextWriter writer)
{
return WriteToAsync(tagHelper, writer, HtmlEncoder.Default);
}
public static async ValueTask WriteToAsync(this TagHelper tagHelper, TextWriter writer, HtmlEncoder htmlEncoder)
{
var uniqueId = Guid.NewGuid().ToString();
var tagHelperContext = new TagHelperContext(new TagHelperAttributeList(), new Dictionary<object, object>(), uniqueId);
var tagHelperOutput = new TagHelperOutput(uniqueId, new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
await tagHelper.ProcessAsync(tagHelperContext, tagHelperOutput);
tagHelperOutput.WriteTo(writer, htmlEncoder);
}
}
これで以下のように簡単にHTMLを取得できます。
var pl = new LoadingPanelTagHelper();
var html = await pl.WriteHtmlAsync();
またTagHelperの中で別のTagHelperのHTMLを取得することも可能になります。保存ボタンの内部にロード中を示すインジケーターを表示するTagHelperを表示するには以下のように書きます。
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
namespace HigLabo.Web.TagHelpers;
[HtmlTargetElement("save-button")]
public class SaveButtonTagHelper : TagHelper
{
public string HxPost { get; set; } = "";
public string Text { get; set; } = T.Text.Save;
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "button";
output.Attributes.Add("class", "large-button");
{
var span = new TagBuilder("span");
span.Attributes.Add("class", "text");
span.InnerHtml.AppendHtml(this.Text);
output.Content.AppendHtml(span);
}
{
var pl = new LoadingPanelTagHelper();
pl.Text = "";
output.Content.AppendHtml(await pl.WriteHtmlAsync());
}
await base.ProcessAsync(context, output);
}
}