こんにちは。
テックリードのTerukiです。
たまにバックエンドで生成したHTMLをクライアントに送らずに取得したくなる場面が出てきます。
例えば、PDFにするためのHTMLをRazor等で書いた後にそれをPDFにしてくれるサービスに渡すなど。
今日はそれの紹介です。
結論
いきなりですがこれで取得できます。
// ServiceProviderとLoggerFactoryはDIから取ってくる
var htmlRenderer = new HtmlRenderer(ServiceProvider, LoggerFactory);
var html = await HtmlRenderer.Dispatcher.InvokeAsync(async () => {
var dictionary = new Dictionary<string, object?> {
["Name"] = name,
["Description"] = description,
};
var parameters = ParameterView.FromDictionary(dictionary);
var output = await htmlRenderer.RenderComponentAsync<ToBePdfComponent>(parameters).ConfigureAwait(false);
return output.ToHtmlString();
}).ConfigureAwait(false);
ToBePdfComponent.razor
ファイル:
@code {
[Parameter]
public required string Name { get; set; }
[Parameter]
public required string Description { get; set; }
}
<h1>@Name</h1>
<p>@Description</p>
めっちゃシンプルです。Dispatcher辺りはややこしいですね。
この記事と組み合わせたらIP制限された環境からはどのURLにアクセスしても同じHTMLを返すなんてこともできそうです。
書くとしたらこんな感じでしょうか。
using var scope = serviceScopeFactory.CreateScope();
var htmlRenderer = new HtmlRenderer(scope.ServiceProvider, scope.ServiceProvider.GetRequiredService<ILoggerFactory>());
var html = await htmlRenderer.Dispatcher.InvokeAsync(async () =>
(await htmlRenderer.RenderComponentAsync<IpRestriction403>()).ToHtmlString()); // Razorコンポーネントを用意
context.Response.Clear();
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
context.Response.ContentType = "text/html";
await context.Response.WriteAsync(html);
だいぶ便利ですね。
参考