使用强类型模型从 Razor 视图页面生成 HTML 电子邮件

问题描述 投票:0回答:1

我正在尝试从 Razor 页面生成 HTML 电子邮件。这对于没有任何模型的 HTML 非常有效。但是,当我添加模型“WelcomeEmailModel”并尝试传递变量时,我在“@Model.UserName”参数上收到以下错误。

“未将对象引用设置为对象的实例。”

模型未传递到视图。

我可以在 ViewData 中看到(见下图),模型“用户名”填充有“Jane Doe”。

我通过谷歌找到的例子不包含模型。是否可以通过这种方式发送模型,还是应该通过其他方式传递模型?

剃刀视图

@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>

电子邮件服务.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);
        }
    }
}
c# asp.net-core razor identity
1个回答
0
投票

请务必删除 razor 视图中的

@page
,因为您的自定义
RenderViewToStringAsync
方法用于渲染 razor 视图,而不是渲染 razor 页面到字符串。

razor 视图和 razor 页面的区别:

Razor Pages 可以使以页面为中心的场景编码比使用控制器和视图更容易、更高效。它的不同之处在于

@page
指令。
 @page
使文件成为 MVC 操作,这意味着它直接处理请求,而不通过控制器。
@page
必须是页面上的第一个 Razor 指令。
@page
影响其他 Razor 构造的行为。

© www.soinside.com 2019 - 2024. All rights reserved.