场景:


我有一个.net core 2.0控制台应用程序,其中包含Razor视图(在我的情况下包含在Embedded Resources中)
我正在使用RazorViewToStringRenderer将视图呈现为字符串。视图是电子邮件模板。


它工作正常,但是当使用预编译视图发布应用程序时,上述方法链接中的FindView返回null。

重现步骤:


下载aspnet/Entropy/samples/Mvc.RenderViewToString示例
发布并运行


如何在运行时查找并渲染预编译视图?

最佳答案

最简单的解决方法是在发布期间禁用预编译视图。如果这是一个选项,则只需在csproj文件中将MvcRazorCompileOnPublish设置为false

<PropertyGroup>
  <TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
  <MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish>
</PropertyGroup>


但是,如果要使用预编译的视图,则需要在ConfigureDefaultServices方法中进行一些修复。

首先,将services.Configure<RazorViewEngineOptions>调用移到AddMvc()之后。否则,您将覆盖由RazorViewEngineOptions添加的AddMvc()配置设置,并且该设置将不会填充必需的数据(由RazorViewEngineOptionsSetup执行的作业)。

在此修复之后,基本渲染将起作用,但是Razor Engine无法定位局部视图和布局。要解决此问题,您需要将不带控制器名称(/Views/{0}.cshtml)的位置格式添加到RazorViewEngineOptions.ViewLocationFormats集合。

在描述了修复程序之后,基于预编译视图的渲染对我来说很好。这里是更正的ConfigureDefaultServices方法:

private static void ConfigureDefaultServices(IServiceCollection services, string customApplicationBasePath)
{
    string applicationName;
    IFileProvider fileProvider;
    if (!string.IsNullOrEmpty(customApplicationBasePath))
    {
        applicationName = Path.GetFileName(customApplicationBasePath);
        fileProvider = new PhysicalFileProvider(customApplicationBasePath);
    }
    else
    {
        applicationName = Assembly.GetEntryAssembly().GetName().Name;
        fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
    }

    services.AddSingleton<IHostingEnvironment>(new HostingEnvironment
    {
        ApplicationName = applicationName,
        WebRootFileProvider = fileProvider,
    });

    var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
    services.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
    services.AddSingleton<DiagnosticSource>(diagnosticSource);
    services.AddLogging();
    services.AddTransient<RazorViewToStringRenderer>();
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.ViewLocationFormats.Add("/Views/{0}.cshtml");

        options.FileProviders.Clear();
        options.FileProviders.Add(fileProvider);
    });
    services.AddMvc();
}

10-08 11:41