使用Asp.Net很容易看到Razor View Engine生成的代码:添加编译错误,错误页面将提供对Razor页面源的访问。
这改变了Asp.Net Core,我在某处读到了在内存中创建代码并且不允许轻松访问该代码。
问题:有人知道如何使用Asp.Net Core访问生成的Razor源代码?
答案 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
。
查看查找区分大小写。如果您的控制器路由搜索名为Index
(Index.cshtml
)的视图,但您已将视图文件命名为index
(index.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