如何查找/渲染预编译的Razor View

时间:2018-04-20 07:58:49

标签: c# razor asp.net-core asp.net-core-mvc

情景:

  • 我有一个包含Razor视图的.net核心2.0控制台应用程序(在我的案例中包含为嵌入式资源)
  • 我正在使用RazorViewToStringRenderer将视图呈现给字符串。视图是电子邮件模板。

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

重现的步骤:

  1. 下载aspnet/Entropy/samples/Mvc.RenderViewToString示例
  2. 发布并运行它
  3. 如何在运行时查找和渲染预编译视图?

3 个答案:

答案 0 :(得分:1)

最简单的解决方法是在发布期间禁用预编译视图。如果是一个选项,那么只需在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();
}

答案 1 :(得分:1)

我不明白为什么,但是在控制台应用程序中,AddMvc()跳过了一个配置步骤-它没有添加提供程序来从程序集中检索预编译视图。

在我的情况下,我使用控制台应用程序(net472)和Razor类库,并将RazorViewToStringRenderer放入该库中。

要添加提供者,我们需要执行以下操作

var viewAssembly = Assembly.Load(typeof(RazorViewToStringRenderer).Assembly.GetName().Name + ".Views");
var viewAssemblyPart = new CompiledRazorAssemblyPart(viewAssembly);
services.AddMvc().PartManager.ApplicationParts.Add(viewAssemblyPart);

完成此步骤后,RazorViewToStringRenderer可以正常工作。

答案 2 :(得分:0)

我在Web项目中使用相同的代码,我不得不将完整的目录信息添加到GetView尝试中。 FindView方法使用View或CSHTML扩展(无需预编译)。但GetView需要并且始终有效(有和没有预编译视图)

var getViewResult = _viewEngine
      .GetView(
          executingFilePath: null, 
          viewPath: $"/Views/{viewName}.cshtml", 
          isMainPage: true);