使用Asp.Net Core时,如何查看为Razor Page生成的代码?

时间:2017-03-24 16:29:16

标签: razor asp.net-core

使用Asp.Net很容易看到Razor View Engine生成的代码:添加编译错误,错误页面将提供对Razor页面源的访问。

这改变了Asp.Net Core,我在某处读到了在内存中创建代码并且不允许轻松访问该代码。

问题:有人知道如何使用Asp.Net Core访问生成的Razor源代码?

3 个答案:

答案 0 :(得分:7)

将以下类添加到ASP.NET Core MVC项目中:

using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

public class CustomCompilationService : DefaultRoslynCompilationService, ICompilationService
{
    public CustomCompilationService(ApplicationPartManager partManager, 
        IOptions<RazorViewEngineOptions> optionsAccessor, 
        IRazorViewEngineFileProviderAccessor fileProviderAccessor, 
        ILoggerFactory loggerFactory) 
        : base(partManager, optionsAccessor, fileProviderAccessor, loggerFactory)
    {
    }

    CompilationResult ICompilationService.Compile(RelativeFileInfo fileInfo, 
        string compilationContent)
    {
        return base.Compile(fileInfo, compilationContent);
    }
}

使用上述类覆盖MVC添加的ICompilationService;

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton<ICompilationService, CustomCompilationService>();
}

Compile CustomCompilationService方法上设置一个断点并查看compilationContent

enter image description here

注释

查看查找区分大小写。如果您的控制器路由搜索名为IndexIndex.cshtml)的视图,但您已将视图文件命名为indexindex.cshtml),则会收到异常:

  

InvalidOperationException:找不到视图'Index'。

答案 1 :(得分:5)

人工愚蠢为ASP.NET核心1.x提供了正确的答案。对于框架的 2.0 版本,可以改为使用自定义剃刀模板引擎:

using Microsoft.AspNetCore.Mvc.Razor.Extensions;
using Microsoft.AspNetCore.Razor.Language;

public class CustomMvcRazorTemplateEngine : MvcRazorTemplateEngine
{
  public CustomMvcRazorTemplateEngine(RazorEngine engine, RazorProject project) : base(engine, project)
  { }

  public override RazorCSharpDocument GenerateCode(RazorCodeDocument codeDocument)
  {
    RazorCSharpDocument razorCSharpDocument = base.GenerateCode(codeDocument);
    // Set breakpoint here for inspecting the generated C# code in razorCSharpDocument.GeneratedCode
    // The razor code can be inspected in the Autos or Locals window in codeDocument.Source._innerSourceDocument._content 
    return razorCSharpDocument;
  }
}

然后覆盖框架的RazorTemplateEngine

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc();
  services.AddSingleton<RazorTemplateEngine, CustomMvcRazorTemplateEngine>();
}

在ASP.NET Core的 2.1 版本中,RazorTemplateEngine似乎是遗留的,上述机制不再起作用。这些变化可能与剃刀视图的预编译有关,但由于我没有参与开发,我只能猜测开发人员的动机。

我现在建议检查在构建或发布时生成的**.Views.dll中的预编译视图,具体取决于您的项目设置。我个人为此目的使用Telerik的JustDecompile。

如果您确实需要程序化解决方案,可以使用自定义阶段挂钩RazorProjectEngine

using Microsoft.AspNetCore.Razor.Language;

namespace Econet.PAG.UI
{
  internal class DebugRazorEnginePhase : IRazorEnginePhase
  {
    public RazorEngine Engine { get; set; }

    public void Execute(RazorCodeDocument codeDocument)
    {
      RazorCSharpDocument razorCSharpDocument = codeDocument.GetCSharpDocument();
      // Set breakpoint here for inspecting the generated C# code in razorCSharpDocument.GeneratedCode
      // The razor code can be inspected in the Autos or Locals window in codeDocument.Source._innerSourceDocument._content 
    }
  }
}

并在创建RazorProjectEngine

时注册
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton(s =>
    {
      var fileSystem = s.GetRequiredService<RazorProjectFileSystem>();
      var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder =>
      {
        RazorExtensions.Register(builder);

        // Roslyn + TagHelpers infrastructure
        var metadataReferenceFeature = s.GetRequiredService<LazyMetadataReferenceFeature>();
        builder.Features.Add(metadataReferenceFeature);
        builder.Features.Add(new CompilationTagHelperFeature());

        // TagHelperDescriptorProviders (actually do tag helper discovery)
        builder.Features.Add(new DefaultTagHelperDescriptorProvider());
        builder.Features.Add(new ViewComponentTagHelperDescriptorProvider());

        builder.Phases.Add(new DebugRazorEnginePhase());
      });
}

请注意,除了添加自定义阶段的行外,AddSingleton中的代码将从Microsoft.Extensions.DependencyInjection.MvcRazorMvcCoreBuilderExtensions.AddRazorViewEngineServices(IServiceCollection services)来源的Microsoft.AspNetCore.Mvc.Razor复制。

答案 2 :(得分:4)

在简单的控制台应用程序中:

using Microsoft.AspNetCore.Razor.Language;

class Program
{
    static void Main(string[] args)
    {
        var sourceDocument = RazorSourceDocument.Create("Hello world", "");
        var codeDocument = RazorCodeDocument.Create(sourceDocument);

        var engine = RazorEngine.Create();
        engine.Process(codeDocument);

        var csharpDocument = codeDocument.GetCSharpDocument();
        var csharp = csharpDocument.GeneratedCode;
        Console.WriteLine(csharp);
    }
}

输出是:

#pragma checksum "" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "7b502c3a1f48c8609ae212cdfb639dee39673f5e"
// <auto-generated/>
#pragma warning disable 1591
namespace Razor
{
    #line hidden
    public class Template
    {
        #pragma warning disable 1998
        public async override global::System.Threading.Tasks.Task ExecuteAsync()
        {
            WriteLiteral("Hello world");
        }
        #pragma warning restore 1998
    }
}
#pragma warning restore 1591