You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Minimal API中将Razor View渲染为字符串实现邮件发送

在ASP.NET Minimal API中使用Razor视图渲染邮件正文

1. 安装必要的NuGet包

首先安装Razor运行时编译相关依赖,确保Minimal API能编译并渲染Razor视图:

Install-Package Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation

2. 配置Program.cs中的服务

Minimal API默认不包含Razor视图相关服务,需要手动注册:

var builder = WebApplication.CreateBuilder(args);

// 注册Razor视图服务及运行时编译
builder.Services.AddControllersWithViews()
    .AddRazorRuntimeCompilation();

// 注册自定义视图渲染服务
builder.Services.AddScoped<IViewRenderService, ViewRenderService>();

// 注册你的邮件发送服务
builder.Services.AddSingleton<YourEmailService>();

var app = builder.Build();

// 其他中间件配置...

app.Run();

3. 实现视图渲染服务

编写一个服务类,通过依赖的Razor引擎组件手动构建视图上下文,将视图渲染为字符串:

public interface IViewRenderService
{
    Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model);
}

public class ViewRenderService : IViewRenderService
{
    private readonly IRazorViewEngine _razorViewEngine;
    private readonly ITempDataProvider _tempDataProvider;
    private readonly IServiceProvider _serviceProvider;

    public ViewRenderService(IRazorViewEngine razorViewEngine,
        ITempDataProvider tempDataProvider,
        IServiceProvider serviceProvider)
    {
        _razorViewEngine = razorViewEngine;
        _tempDataProvider = tempDataProvider;
        _serviceProvider = serviceProvider;
    }

    public async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model)
    {
        // 手动构建HttpContext(无请求上下文时也能运行)
        var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
        var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

        // 查找指定视图
        var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);
        if (!viewResult.Success)
        {
            throw new InvalidOperationException($"视图 {viewName} 不存在");
        }

        // 用StringWriter捕获渲染结果
        using var sw = new StringWriter();
        var viewContext = new ViewContext(
            actionContext,
            viewResult.View,
            new ViewDataDictionary<TModel>(
                new EmptyModelMetadataProvider(),
                new ModelStateDictionary())
            {
                Model = model
            },
            new TempDataDictionary(httpContext, _tempDataProvider),
            sw,
            new HtmlHelperOptions()
        );

        await viewResult.View.RenderAsync(viewContext);
        return sw.ToString();
    }
}

4. 创建Razor邮件视图

在项目根目录下创建Views/Email文件夹,添加RequestDenied.cshtml作为邮件模板:

@model YourNamespace.EmailRequestModel

<!DOCTYPE html>
<html>
<head>
    <style>
        .email-box { padding: 24px; font-family: 'Segoe UI', Arial, sans-serif; max-width: 600px; margin: 0 auto; }
        .system-title { color: #2d3748; font-size: 19px; font-weight: 600; margin-bottom: 16px; }
        .content-text { color: #4a5568; line-height: 1.6; }
    </style>
</head>
<body>
    <div class="email-box">
        <h3>请求已拒绝通知</h3>
        <div class="system-title">系统名称:@Model.SystemName</div>
        <div class="content-text">您提交的请求已被系统拒绝,请联系管理员了解详细原因。</div>
    </div>
</body>
</html>

5. 修改邮件发送方法

注入视图渲染服务,替换原有的硬编码邮件正文:

private readonly IViewRenderService _viewRenderService;
private readonly string _eMailFrom;
private readonly string _mailServer;

// 构造函数注入视图渲染服务
public YourEmailService(IViewRenderService viewRenderService, IConfiguration configuration)
{
    _viewRenderService = viewRenderService;
    _eMailFrom = configuration["EmailSettings:From"];
    _mailServer = configuration["EmailSettings:Server"];
}

public async Task<bool> SendRequestDenied(string systemName)
{
    try
    {
        var model = new EmailRequestModel { SystemName = systemName };
        // 渲染视图为HTML字符串
        string emailBody = await _viewRenderService.RenderViewToStringAsync("Email/RequestDenied", model);

        MailMessage message = new MailMessage();
        message.From = new MailAddress(_eMailFrom);
        message.Subject = $"[{systemName}] 请求已拒绝";
        message.Body = emailBody;
        message.IsBodyHtml = true;

        List<string> emailRequests = GetListOfEmails();
        foreach (string email in emailRequests)
        {
            message.To.Add(email);
        }

        using SmtpClient smtpClient = new SmtpClient(_mailServer);
        smtpClient.Send(message);
        return true;
    }
    catch (Exception ex)
    {
        // 可添加日志记录逻辑
        return false;
    }
}

注意事项

  • 视图路径需对应实际文件位置:Email/RequestDenied对应Views/Email/RequestDenied.cshtml,共享视图可使用Shared/ViewName格式。
  • 确保视图文件的"生成操作"设置为"内容",避免编译时被忽略。
  • 该方案支持无请求上下文的场景(如后台任务触发邮件),无需依赖HttpContext。

内容的提问来源于stack exchange,提问作者Abdullah Ergun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 10:08:22