从 AspNetCore TestHost 运行时编译 Razor 期间出现 CompilationFailedException
CompilationFailedException during runtime compilation of Razor from AspNetCore TestHost
我有 ASP.Net MVC 应用程序,其中一部分是将 Razor 视图编译为字符串。该代码与此示例非常相似:
https://long2know.com/2017/08/rendering-and-emailing-embedded-razor-views-with-net-core/
我在 Startup.cs 中以这种方式注册了 Razor 引擎:
var viewAssembly = typeof(HtmlGeneratorService).GetTypeInfo().Assembly;
var fileProvider = new EmbeddedFileProvider(
viewAssembly,
"ApplicationServices.Widgets.Html.Templates");
services.Configure<MvcRazorRuntimeCompilationOptions>(options => {
options.FileProviders.Clear();
options.FileProviders.Add(fileProvider);
});
services.AddRazorPages().AddRazorRuntimeCompilation();
在测试项目中我有这个设置:
var builder = new HostBuilder()
.ConfigureWebHost(webHost =>
{
webHost.UseTestServer();
webHost.UseStartup<Startup>();
});
var host = await builder.StartAsync();
HttpClient = host.GetTestClient();
但是当我使用这个 HttpClient 调用我的端点时,IRazorViewEngine.GetView 开始抛出奇怪的异常:
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.CompilationFailedException: 'One or more compilation failures occurred:
rnouw0xu.21w(4,41): error CS0234: The type or namespace name 'Razor' does not exist in the namespace 'Microsoft.AspNetCore' (are you missing an assembly reference?)
rnouw0xu.21w(4,82): error CS0518: Predefined type 'System.Type' is not defined or imported
rnouw0xu.21w(4,110): error CS0518: Predefined type 'System.String' is not defined or imported
rnouw0xu.21w(4,127): error CS0518: Predefined type 'System.String' is not defined or imported
rnouw0xu.21w(8,11): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
rnouw0xu.21w(9,11): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
rnouw0xu.21w(10,11): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
rnouw0xu.21w(11,11): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
rnouw0xu.21w(13,36): error CS0234: The type or namespace name 'Rendering' does not exist in the namespace 'Microsoft.AspNetCore.Mvc' (are you missing an assembly reference?)
rnouw0xu.21w(14,36): error CS0234: The type or namespace name 'ViewFeatures' does not exist in the namespace 'Microsoft.AspNetCore.Mvc' (are you missing an assembly reference?)
rnouw0xu.21w(29,35): error CS0234: The type or namespace name 'Razor' does not exist in the namespace 'Microsoft.AspNetCore' (are you missing an assembly reference?)
rnouw0xu.21w(29,78): error CS0518: Predefined type 'System.String' is not defined or imported
rnouw0xu.21w(29,87): error CS0518: Predefined type 'System.String' is not defined or imported
我尝试以多种不同的方式修复此错误,但看起来我被困在这里了。
看来我在这篇文章中找到了答案:
https://github.com/aspnet/Razor/issues/1212
我刚刚将此代码添加到我的 test.csproj 文件中:
<Target Name="CopyDepsFiles" AfterTargets="Build" Condition="'$(TargetFramework)'!=''">
<ItemGroup>
<DepsFilePaths Include="$([System.IO.Path]::ChangeExtension('%(_ResolvedProjectReferencePaths.FullPath)', '.deps.json'))" />
</ItemGroup>
<Copy SourceFiles="%(DepsFilePaths.FullPath)" DestinationFolder="$(OutputPath)" Condition="Exists('%(DepsFilePaths.FullPath)')" />
</Target>
只是稍微扩展了已批准的答案,因为在升级到 .NET 6 时建议的修复对我不起作用,运行时仍然无法找到程序集,直到我明确添加 AddApplicationPart(assembly)
调用IMvcBuilder
.
还有一个小的简化是将选项 lambda 传递给 AddRazordRuntimeCompilation
调用,在这种情况下可以删除 services.Configure<MvcRazorRuntimeCompilationOptions>
。
它可能由于多种原因而失败(这是一个 Windows 服务项目,视图在一个单独的 dll 中),但无论如何这是我从网上收集的各种修复程序的汇编:
// this part is needed if you don't have a valid IWebHostEnvironment
// service registered, in which case you need to create your own dummy
// implementation because Razor needs IWebHostEnvironment.ApplicationName
// (it should return Assembly.GetEntryAssembly().GetName().Name, and you
// can leave other properties null)
services.AddSingleton<IWebHostEnvironment, DummyHostingEnvironment>();
services.AddSingleton<IHostEnvironment, DummyHostingEnvironment>();
// this also needs to be registered as two separate dependencies
// if you're getting "Unable to resolve service for type
// 'System.Diagnostics.DiagnosticListener'"
// (see https://github.com/dotnet/aspnetcore/issues/14544)
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
services.AddSingleton<DiagnosticSource>(diagnosticSource);
services.AddSingleton<DiagnosticListener>(diagnosticSource);
// make sure you specify correct assemblies, in case the views
// are in a separate dll
var assemblyWithTemplates = ...;
var assemblyReferencingTheRazorPackage = ...;
services
.AddRazorPages()
.AddApplicationPart(assemblyReferencingTheRazorPackage ) // <-- added this
.AddRazorRuntimeCompilation(options =>
{
// important to clear because some of them are null
options.FileProviders.Clear();
// resolve views as embedded resources
options.FileProviders.Add(new EmbeddedFileProvider(assemblyWithTemplates));
});
然后还将已接受答案中的代码添加到 .csproj 文件,以便正确复制 .deps 文件。
我有 ASP.Net MVC 应用程序,其中一部分是将 Razor 视图编译为字符串。该代码与此示例非常相似: https://long2know.com/2017/08/rendering-and-emailing-embedded-razor-views-with-net-core/
我在 Startup.cs 中以这种方式注册了 Razor 引擎:
var viewAssembly = typeof(HtmlGeneratorService).GetTypeInfo().Assembly;
var fileProvider = new EmbeddedFileProvider(
viewAssembly,
"ApplicationServices.Widgets.Html.Templates");
services.Configure<MvcRazorRuntimeCompilationOptions>(options => {
options.FileProviders.Clear();
options.FileProviders.Add(fileProvider);
});
services.AddRazorPages().AddRazorRuntimeCompilation();
在测试项目中我有这个设置:
var builder = new HostBuilder()
.ConfigureWebHost(webHost =>
{
webHost.UseTestServer();
webHost.UseStartup<Startup>();
});
var host = await builder.StartAsync();
HttpClient = host.GetTestClient();
但是当我使用这个 HttpClient 调用我的端点时,IRazorViewEngine.GetView 开始抛出奇怪的异常:
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.CompilationFailedException: 'One or more compilation failures occurred:
rnouw0xu.21w(4,41): error CS0234: The type or namespace name 'Razor' does not exist in the namespace 'Microsoft.AspNetCore' (are you missing an assembly reference?)
rnouw0xu.21w(4,82): error CS0518: Predefined type 'System.Type' is not defined or imported
rnouw0xu.21w(4,110): error CS0518: Predefined type 'System.String' is not defined or imported
rnouw0xu.21w(4,127): error CS0518: Predefined type 'System.String' is not defined or imported
rnouw0xu.21w(8,11): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
rnouw0xu.21w(9,11): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
rnouw0xu.21w(10,11): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
rnouw0xu.21w(11,11): error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
rnouw0xu.21w(13,36): error CS0234: The type or namespace name 'Rendering' does not exist in the namespace 'Microsoft.AspNetCore.Mvc' (are you missing an assembly reference?)
rnouw0xu.21w(14,36): error CS0234: The type or namespace name 'ViewFeatures' does not exist in the namespace 'Microsoft.AspNetCore.Mvc' (are you missing an assembly reference?)
rnouw0xu.21w(29,35): error CS0234: The type or namespace name 'Razor' does not exist in the namespace 'Microsoft.AspNetCore' (are you missing an assembly reference?)
rnouw0xu.21w(29,78): error CS0518: Predefined type 'System.String' is not defined or imported
rnouw0xu.21w(29,87): error CS0518: Predefined type 'System.String' is not defined or imported
我尝试以多种不同的方式修复此错误,但看起来我被困在这里了。
看来我在这篇文章中找到了答案: https://github.com/aspnet/Razor/issues/1212
我刚刚将此代码添加到我的 test.csproj 文件中:
<Target Name="CopyDepsFiles" AfterTargets="Build" Condition="'$(TargetFramework)'!=''">
<ItemGroup>
<DepsFilePaths Include="$([System.IO.Path]::ChangeExtension('%(_ResolvedProjectReferencePaths.FullPath)', '.deps.json'))" />
</ItemGroup>
<Copy SourceFiles="%(DepsFilePaths.FullPath)" DestinationFolder="$(OutputPath)" Condition="Exists('%(DepsFilePaths.FullPath)')" />
</Target>
只是稍微扩展了已批准的答案,因为在升级到 .NET 6 时建议的修复对我不起作用,运行时仍然无法找到程序集,直到我明确添加 AddApplicationPart(assembly)
调用IMvcBuilder
.
还有一个小的简化是将选项 lambda 传递给 AddRazordRuntimeCompilation
调用,在这种情况下可以删除 services.Configure<MvcRazorRuntimeCompilationOptions>
。
它可能由于多种原因而失败(这是一个 Windows 服务项目,视图在一个单独的 dll 中),但无论如何这是我从网上收集的各种修复程序的汇编:
// this part is needed if you don't have a valid IWebHostEnvironment
// service registered, in which case you need to create your own dummy
// implementation because Razor needs IWebHostEnvironment.ApplicationName
// (it should return Assembly.GetEntryAssembly().GetName().Name, and you
// can leave other properties null)
services.AddSingleton<IWebHostEnvironment, DummyHostingEnvironment>();
services.AddSingleton<IHostEnvironment, DummyHostingEnvironment>();
// this also needs to be registered as two separate dependencies
// if you're getting "Unable to resolve service for type
// 'System.Diagnostics.DiagnosticListener'"
// (see https://github.com/dotnet/aspnetcore/issues/14544)
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
services.AddSingleton<DiagnosticSource>(diagnosticSource);
services.AddSingleton<DiagnosticListener>(diagnosticSource);
// make sure you specify correct assemblies, in case the views
// are in a separate dll
var assemblyWithTemplates = ...;
var assemblyReferencingTheRazorPackage = ...;
services
.AddRazorPages()
.AddApplicationPart(assemblyReferencingTheRazorPackage ) // <-- added this
.AddRazorRuntimeCompilation(options =>
{
// important to clear because some of them are null
options.FileProviders.Clear();
// resolve views as embedded resources
options.FileProviders.Add(new EmbeddedFileProvider(assemblyWithTemplates));
});
然后还将已接受答案中的代码添加到 .csproj 文件,以便正确复制 .deps 文件。