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

使用强类型模型从Razor视图生成HTML邮件时遇空引用错误

Razor页面生成HTML邮件时模型传递失败问题

我尝试用Razor页面生成HTML邮件,无模型时运行正常,但添加强类型模型WelcomeEmailModel并传递变量后,在@Model.UserName处出现错误:'Object reference not set to an instance of an object.',模型未传递到视图。查看ViewData发现Username字段已填充为“Jane Doe”,但谷歌找到的示例均未涉及模型,请问是否可通过此方式传递模型,或需采用其他方式?

相关代码

Razor View

@page
@model WelcomeEmailModel

<!DOCTYPE html>
<html>
<head>
    <title>Welcome to Our Website!</title>
</head>
<body>
    <h2>Welcome, @Model.UserName!</h2>
    <p>Thank you for signing up to our website. We're excited to have you on board!</p>
</body>
</html>

EmailService.cs

namespace FlightLog.Services
{
    public class EmailService
    {
        private readonly EmailClient _emailClient;
        private readonly string _senderEmailAddress;
        private readonly IRazorViewEngine _razorViewEngine;
        private readonly IServiceProvider _serviceProvider;

        public EmailService(string connectionString, string senderEmailAddress, IRazorViewEngine razorViewEngine, IServiceProvider serviceProvider)
        {
            _emailClient = new EmailClient(connectionString);
            _senderEmailAddress = senderEmailAddress;
            _razorViewEngine = razorViewEngine;
            _serviceProvider = serviceProvider;
        }

        public async Task<string> RenderViewToStringAsync<TModel>(string viewName, TModel model)
        {
            var actionContext = GetActionContext();
            var viewEngineResult = _razorViewEngine.FindView(actionContext, viewName, false);
            //var viewEngineResult = _razorViewEngine.GetView("~/Views/EmailTemplates", $"{viewName}.cshtml", false);

            if (!viewEngineResult.Success)
            {
                throw new InvalidOperationException($"Unable to find view '{viewName}'");
            }

         
            using (var sw = new StringWriter())
            {
                var tempDataSerializer = (TempDataSerializer)_serviceProvider.GetService(typeof(TempDataSerializer));
                var tempDataProvider = new SessionStateTempDataProvider(tempDataSerializer);

                var viewContext = new ViewContext(
                    actionContext,
                    viewEngineResult.View,
                    new ViewDataDictionary<TModel>(
                    metadataProvider: new EmptyModelMetadataProvider(),
                    modelState: new ModelStateDictionary())
                    {
                        Model = model
                    },
                    new TempDataDictionary(actionContext.HttpContext, tempDataProvider),
                    sw,
                    new HtmlHelperOptions()
                );

                await viewEngineResult.View.RenderAsync(viewContext);

                return sw.ToString();
            }
        }

        private ActionContext GetActionContext()
        {
            var httpContext = new DefaultHttpContext
            {
                RequestServices = _serviceProvider
            };
            return new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
        }

        public async Task SendEmailAsync(string recipient, string subject, string body)
        {

            var emailContent = new EmailContent(subject)
            {
                Html = body
            };

            var emailMessage = new EmailMessage(
                  _senderEmailAddress,
                  recipient,
                  emailContent);

            await _emailClient.SendAsync(WaitUntil.Completed, emailMessage, CancellationToken.None);
        }

        public async Task SendWelcomeEmailAsync(string recipient, string userName)
        {
            var viewModel = new WelcomeEmailModel
            {
                UserName = userName
            };

            string emailBody = await RenderViewToStringAsync("WelcomeEmail", viewModel);
            await SendEmailAsync(recipient, "Welcome to Our Website!", emailBody);
        }
    }
}

问题原因及解决方法

问题出在你用了带@page指令的Razor页面,而非普通Razor视图。Razor页面是独立的页面组件,自带路由和模型绑定逻辑,直接用IRazorViewEngine渲染时,不会自动接收你传入的模型。

具体修复步骤

  1. 把Razor页面改成普通Razor视图
    删掉Razor文件顶部的@page指令,因为@page会让它变成独立页面,而非可复用的模板。修改后代码如下:
@model WelcomeEmailModel

<!DOCTYPE html>
<html>
<head>
    <title>Welcome to Our Website!</title>
</head>
<body>
    <h2>Welcome, @Model.UserName!</h2>
    <p>Thank you for signing up to our website. We're excited to have you on board!</p>
</body>
</html>
  1. 调整视图查找逻辑
    在RenderViewToStringAsync方法中,用GetView替代FindView,因为普通视图不在Razor页面的默认查找路径里。取消注释原有GetView代码并调整路径到你的模板实际存放位置:
// 替换原来的FindView代码
var viewEngineResult = _razorViewEngine.GetView("~/Views/EmailTemplates", $"{viewName}.cshtml", false);

注意:路径要和你项目里模板的实际位置对应,比如存放在Views/Shared下就改成对应路径。

  1. 验证模型传递
    你原有的ViewDataDictionary初始化逻辑是正确的,只要视图改成普通Razor视图,模型就能正常传递,无需修改其他绑定代码。

额外说明

  • Razor页面(带@page)适合做独立业务页面,不适合邮件模板这种需要复用、接收外部模型的场景,普通Razor视图才是正确选择。
  • 如果硬要使用Razor页面,需要额外处理页面的模型绑定逻辑,流程会更复杂,不推荐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 01:19:53