场景:
我有一个.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();
}