【问题标题】:How do I find/render precompiled Razor View如何查找/呈现预编译的 Razor 视图
【发布时间】:2018-04-20 07:58:48
【问题描述】:

场景:

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

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

重现步骤:

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

如何在运行时查找和呈现预编译视图?

【问题讨论】:

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


【解决方案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 完美运行。

【讨论】:

  • CompiledRazorAssemblyPart 是我尝试从 Azure Function v3 开始工作时的诀窍。
【解决方案2】:

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

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

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

首先,将services.Configure&lt;RazorViewEngineOptions&gt; 调用移动到AddMvc() 之后。否则,您将覆盖AddMvc() 添加的RazorViewEngineOptions 配置设置,并且不会填充所需的数据(RazorViewEngineOptionsSetup 执行的作业)。

在此修复后,基本渲染将正常工作,但 Razor 引擎将无法定位部分视图和布局。要解决此问题,您需要将不带控制器名称 (/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();
}

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      • 1970-01-01
      • 2011-07-26
      相关资源
      最近更新 更多