项目找不到带有键_Layout.cshtml的模板

Ash*_*h K 7 c# razor .net-5 razorlight

我在使用_Layout.cshtmlin的嵌入式资源时正在努力使电子邮件正常工作FluentEmail

这是我收到的异常错误:

Project can not find template with key _Layout.cshtml
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止的设置:

在ConfigureServices中Program.cs,我添加了RazorRenderer以下内容:

//Set email service using FluentEmail
 services.AddFluentEmail("appname@domain.com")
 .AddRazorRenderer(typeof(Program))
 .AddSmtpSender("smtp.somesmtp.com", 25)
 .AddSmtpSender(new System.Net.Mail.SmtpClient() { });
Run Code Online (Sandbox Code Playgroud)

在我的内部NotificationService.cs,我总是陷入异常块:

private async Task SendEmailAsync<TModel>(string subject, TModel model)
{
    try
    {
        using (var scope = _serviceProvider.CreateScope())
        {
            var email = await scope.ServiceProvider.GetRequiredService<IFluentEmail>()
                    .To(string.Join(";", _emailRecipients))
                    .Subject(subject)
                    .UsingTemplateFromEmbedded("AppName.Views.Emails.SomeReport.cshtml", model, GetType().Assembly)
                    .SendAsync();
        }
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Failed to send email. Check exception for more information.");
    }
}
Run Code Online (Sandbox Code Playgroud)

SomeReport.cshtml里面Views\Emails\SomeReport.cshtml看起来像这样:

@using System;
@using RazorLight;
@using System.Collections.Generic;
@using AppName.Models;

@inherits TemplatePage<IEnumerable<SomeReport>>
@{
    @* For working with Embedded Resource Views *@
    Layout = "_Layout.cshtml";
}

@* Work with the Model here... *@
Run Code Online (Sandbox Code Playgroud)

_Layout.cshtml里面Views\Shared\_Layout.cshtml看起来像这样:

@using RazorLight;
@* Some common layout styles here *@
@RenderBody()
Run Code Online (Sandbox Code Playgroud)

SomeReport.cshtml都是_Layout.cshtml嵌入式资源:

我的参考文献已经RazorLight通过FluentEmail.Razor包。

如果有帮助,这是一个.NET 5 Worker Service项目,我还在文件中添加了PreserveCompilationContext和:PreserveCompilationReferences.csproj

<PropertyGroup>
  <TargetFramework>net5.0</TargetFramework>
  <PreserveCompilationContext>true</PreserveCompilationContext>
  <PreserveCompilationReferences>true</PreserveCompilationReferences>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

我已经到处查看,但仍然没有找到解决方案。这么简单的事情要做起来却很困难。请帮忙。

谢谢!

Ash*_*h K 3

长话短说

点注1:

在视图中指定的路径_Layout.cshtml必须相对于您在添加 FluentEmail 时输入的嵌入资源根目录。例如:

.AddRazorRenderer(typeof(Program))
Run Code Online (Sandbox Code Playgroud)

由于 myProgram.csViews文件夹位于同一级别,因此要_Layout.cshtml通过 进行定位SomeReport.cshtml,我的路径需要为:

@{
    Layout = "Views.Shared._Layout.cshtml";
}
Run Code Online (Sandbox Code Playgroud)

注意事项2:

指定视图的路径必须是从程序集名称开始的完整路径。例如:

var razorTemplatePath = "AppName.Views.Emails.SomeReport.cshtml";
Run Code Online (Sandbox Code Playgroud)

现在它就像一个魅力!


我的完整设置

ConfigureServicesProgram.cs-->的方法内部

// Set email service using FluentEmail
services.AddFluentEmail("appname@domain.com")
        // For Fluent Email to find _Layout.cshtml, just mention here where your views are. This took me hours to figure out. - AshishK
        //.AddRazorRenderer(@$"{Directory.GetCurrentDirectory()}/Views/")
        .AddRazorRenderer(typeof(Program)) //If you want to use views as embedded resource, use this
        .AddSmtpSender("smtp.somesmtp.com", 25)
        .AddSmtpSender(new System.Net.Mail.SmtpClient() { });
Run Code Online (Sandbox Code Playgroud)

在我的里面FluentEmailService.cs

public class FluentEmailService
{
    private readonly IFluentEmailFactory _fluentEmailFactory;
    private readonly ILogger<FluentEmailService> _logger;

    // Keep in mind that only the Singleton services can be injected through the constructor - AshishK.
    public FluentEmailService(ILogger<FluentEmailService> logger, IFluentEmailFactory fluentEmailFactory)
    {
        _logger = logger;
        _fluentEmailFactory = fluentEmailFactory;
    }

    public async Task<SendResponse> SendEmailAsync<TModel>(string subject, string razorTemplatePath, TModel model, string semicolonSeparatedEmailRecipients)
    {
        try
        {
            // var razorTemplatePathExample = "AppName.Views.Emails.SomeReport.cshtml";
            // var semicolonSeparatedEmailRecipientsExample = "CoolGuy@company.com;ChillGuy@company.com";
            // 'model' is whatever you send to the View. For eg: @model IEnumerable<SomeReport> that we put at the top of SomeReport.cshtml view (see below).

            var email = await _fluentEmailFactory
                            .Create()
                            .To(semicolonSeparatedEmailRecipients)
                            .Subject(subject)
                            .UsingTemplateFromEmbedded(razorTemplatePath, model, GetType().Assembly) //If you want to use embedded resource Views.
                            .SendAsync();
            return email;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to send email. Check exception for more information.");
            return new SendResponse() { ErrorMessages = new string[] { ex.Message } };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

SomeReport.cshtml我的视图 ( , )的属性_Layout.cshtml如下所示:

(您不需要为_ViewImports.cshtml和执行此操作_ViewStart.cshtml。)

我的视图SomeReport.cshtml在里面Views\Emails\SomeReport.cshtml,看起来像这样:

@model IEnumerable<SomeReport>

@{
    Layout = "Views.Shared._Layout.cshtml";
}

@* Work with the Model here... *@
Run Code Online (Sandbox Code Playgroud)

_Layout.cshtml里面Views\Shared\_Layout.cshtml看起来像这样:

<!DOCTYPE html>
<html>
...
</html>
Run Code Online (Sandbox Code Playgroud)

我的参考文献已经RazorLight通过FluentEmail.Razor包。

Razorlight 的设置在我的 .csproj 文件中如下所示:

<PropertyGroup>
  <!-- This group contains project properties for RazorLight on .NET Core -->
  <PreserveCompilationContext>true</PreserveCompilationContext>
  <MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
  <MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)