首页 > 解决方案 > .NET Core 3.1 Sdk.Worker 与 Sdk.Web Razor 模板?(Sdk.Web 做了什么来允许 Razor 模板?)

问题描述

我正在尝试使用这个示例来展示如何将 Razor 模板呈现为字符串,以便我可以将它们用于丰富的电子邮件模板。

https://github.com/aspnet/Entropy/tree/master/samples/Mvc.RenderViewToString

我已经根据这个 repo 更新了代码,它描述了如何将示例更新到 .NET Core 3.1

https://github.com/scottsauber/RazorHtmlEmails

我稍微改变了它,因为我正在尝试使用 BackgroundService Worker 来根据数据库更改执行渲染和传输。

根据这个问题的答案(Can a Worker Service be called and/or used inside an existing ASPNET.Core web project?)多个进程可以同时运行。所以我像这样设置我的主机构建器。

public static IHostBuilder CreateHostBuilder(string[] args)
{
    return Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .ConfigureServices((hostContext, services) =>
        {
            services.AddDbContext<MyDataContext>(dbOptions =>
            {
                dbOptions.UseSqlServer(
                    hostContext.Configuration.GetConnectionString("db"),
                    sqlOptions => sqlOptions.EnableRetryOnFailure()
                );
            });
            // This is our main worker that will loop
            services.AddHostedService<Worker>();
            // Add NLog as the logging handler
            services.AddLogging(loggingBuilder =>
            {
                loggingBuilder.ClearProviders();
                loggingBuilder.SetMinimumLevel(LogLevel.Trace);
                loggingBuilder.AddNLog(hostContext.Configuration);
            });
        })
        // Add our template renderer
        .ConfigureWebHostDefaults(builder =>
        {
            builder.UseStartup<RazorStartup>();
        });
}

和我的 RazorBuilder 一样..

public void ConfigureServices(IServiceCollection services)
        {
            services.AddTransient<IRazorViewToStringRenderer, RazorViewToStringRenderer>();
            services.AddRazorPages();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            var factory = app.ApplicationServices.GetService<IServiceScopeFactory>();
            using (var scope = factory.CreateScope())
            {
                var confirmAccountModel = new ConfirmAccountEmailViewModel($"NOOOOO");
                var service = scope.ServiceProvider.GetService<IRazorViewToStringRenderer>();
                var result = service.RenderViewToStringAsync("/Views/Emails/ConfirmAccount/ConfirmAccountEmail.cshtml", confirmAccountModel).Result;
                Console.WriteLine(result);
            }

        }

这一切...... “工作” ......只要我将目标SDK从更改 <Project Sdk="Microsoft.NET.Sdk.Worker"><Project Sdk="Microsoft.NET.Sdk.Web">

但是当我这样做时,我ILogger的工人失去了写入控制台的能力。所以很明显,他们Sdk.Worker正在做一些他们Sdk.Web没有做的设置。

当我使用时Sdk.Worker,我收到关于无法找到视图的错误。这意味着那Sdk.Web显然是在做一些Sdk.Worker不是的事情。

System.AggregateException
  HResult=0x80131500
  Message=One or more errors occurred. (Unable to find view '/Views/Emails/ConfirmAccount/ConfirmAccountEmail.cshtml'. The following locations were searched:
/Views/Emails/ConfirmAccount/ConfirmAccountEmail.cshtml)
  Source=System.Private.CoreLib
  StackTrace:
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at CompoundAlertProcessor.RazorStartup.Configure(IApplicationBuilder app, IWebHostEnvironment env) in C:\Users\c.rice\Documents\Solutions\GIT\CompoundAlertProcessor\CompoundAlertProcessor\RazorStartup.cs:line 46
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass13_0.<UseStartup>b__2(IApplicationBuilder app)
   at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.GenericWebHostService.<StartAsync>d__31.MoveNext()

  This exception was originally thrown at this call stack:
    CompoundAlertProcessor.Razor.Services.RazorViewToStringRenderer.FindView(Microsoft.AspNetCore.Mvc.ActionContext, string) in RazorViewToStringRenderer.cs
    CompoundAlertProcessor.Razor.Services.RazorViewToStringRenderer.RenderViewToStringAsync<TModel>(string, TModel) in RazorViewToStringRenderer.cs

Inner Exception 1:
InvalidOperationException: Unable to find view '/Views/Emails/ConfirmAccount/ConfirmAccountEmail.cshtml'. The following locations were searched:
/Views/Emails/ConfirmAccount/ConfirmAccountEmail.cshtml

我一直在玩包和设置,试图弄清楚魔术 Sdk.Web在做什么,Sdk.Worker但我不知道。我知道 SDK 会在幕后加载和编排很多事情,以使您更容易实现所需的结果,但我找不到任何可以说明实际在做什么的事情。

我担心尝试使用有基础的工人Sdk.Web会有其他我现在无法预见的变化。像这样使用它是否安全?有什么办法让我只取我需要的碎片Sdk.Web并将它们注入Sdk.Worker

我是否应该放弃使用完整的 Razor,而是尝试使用RazorLite 之类的东西,就像在 .net 标准 2.1 / Core 3.1 中描述的Razor 电子邮件模板一样?我总是对多年未更新的项目保持警惕。

标签: c#asp.net-mvcasp.net-core

解决方案


推荐阅读