using Infrastructure.Email.Templates.Mail; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Web.HtmlRendering; using Microsoft.Extensions.Logging; namespace Infrastructure.Email.Templates.Rendering; /// /// Service for rendering Razor email templates to HTML using HtmlRenderer. /// /// /// The service provider used to resolve dependencies for the Razor component rendering /// pipeline. /// /// The logger factory passed to the used to render components. public class EmailTemplateProvider(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) : IEmailTemplateProvider { /// /// Renders the UserRegisteredEmail template with the specified parameters. /// /// The username to include in the email /// The email confirmation link /// The rendered HTML string public async Task RenderUserRegisteredEmailAsync( string username, string confirmationLink ) { Dictionary parameters = new() { { nameof(UserRegistration.Username), username }, { nameof(UserRegistration.ConfirmationLink), confirmationLink }, }; return await RenderComponentAsync(parameters); } /// /// Renders the ResendConfirmation template with the specified parameters. /// /// The username to include in the email /// The new confirmation link /// The rendered HTML string public async Task RenderResendConfirmationEmailAsync( string username, string confirmationLink ) { Dictionary parameters = new() { { nameof(ResendConfirmation.Username), username }, { nameof(ResendConfirmation.ConfirmationLink), confirmationLink }, }; return await RenderComponentAsync(parameters); } /// /// Generic method to render any Razor component to HTML. /// Creates a scoped , dispatches the render onto its renderer thread, /// and returns the resulting HTML string. /// /// The type of the Razor component to render. /// A dictionary of parameter names and values to pass to the component. /// The rendered HTML string for the component. private async Task RenderComponentAsync( Dictionary parameters ) where TComponent : IComponent { await using HtmlRenderer htmlRenderer = new(serviceProvider, loggerFactory); string html = await htmlRenderer.Dispatcher.InvokeAsync(async () => { ParameterView parameterView = ParameterView.FromDictionary(parameters); HtmlRootComponent output = await htmlRenderer.RenderComponentAsync( parameterView ); return output.ToHtmlString(); }); return html; } }