Describe the bug
ArgumentNullException when performing AspNetCore Integration Tests using Microsoft.AspNetCore.TestHost.TestServer
Value cannot be null.
Parameter name: operatingAssembly (See inner exception for details.) --->
System.ArgumentNullException: Value cannot be null.
Parameter name: operatingAssembly

at RazorLight.Compilation.RoslynCompilationService..ctor(IMetadataReferenceManager referenceManager, Assembly operatingAssembly)

at RazorLight.RazorLightEngineBuilder.Build()

at Services.Contract.IoC.ContractDomainModule.<>c.<Load>b__0_0(IComponentContext x)

To reproduce:
Run a test class library targeting .NET Framework 4.7.1. but running a .NETCore api. Inject the RazorlightEngine in a controller, query the controller end point and wait for it to throw.
Information (please complete the following information):
I'm getting the same exception in a .NET Framework 4.6.1 MSTest project -- but not when I'm running the ASP.NET Core project...
operatingAssembly must be null from a test project?
+1
Too many problems with this project. I finally must give up.
Just pitfall after pitfall. Absolutely brutal.
Having the same issue, trying to unit test my code.
you can get a step closer by on your engine builder adding .SetOperatingAssembly(Assembly assembly) however this will still error but with a different error message regarding DependencyContext.
I have a .netframework project and I had a similar issue. You need to call "SetOperatingAssembly" and pass the assembly where you actually use the razor engine. To make this work I created a factory that is easily injectable and it can create the razor engine wherever and whenever I need it.
Example of the factory:
public class RazorEngineFactory : IRazorEngineFactory
{
public IRazorLightEngine Create()
{
return new RazorLightEngineBuilder()
.SetOperatingAssembly(Assembly.GetCallingAssembly())
.UseFileSystemProject(Directory.GetCurrentDirectory())
.UseMemoryCachingProvider()
.Build();
}
}
Just inject this factory and use it to create the razor engine instead of directly injecting the engine.
By the way, i am using the filesystem resource type, just change it to embedded as you need.
@BarsikV Thanks. Please update the README.md via PR. Very easy to do and doesn't require cloning the git repo locally.
That said, as a code/peer review, perhaps Create() should take a parameter to avoid JIT in-line optimization changing the calling assembly value:
c#
public class RazorEngineFactory : IRazorEngineFactory
{
public IRazorLightEngine Create(Assembly operatingAssembly = null)
{
return new RazorLightEngineBuilder()
.SetOperatingAssembly(operatingAssembly ?? Assembly.GetCallingAssembly())
.UseFileSystemProject(Directory.GetCurrentDirectory())
.UseMemoryCachingProvider()
.Build();
}
}
you can then call razorEngineFactory.Create(this.GetType().Assembly)) which will be invariant under all optimizations.
I ended up implementing the interface from https://github.com/toddams/RazorLight/issues/202#issuecomment-607912964 as RazorLightEngineWithFileSystemProjectFactory.
It is a somewhat superfluous interface, but most people are probably calling RazorLight with a file system, so it makes sense to give them something standard to hook into. It also frankly will make reading tests easier.
Most helpful comment
Just pitfall after pitfall. Absolutely brutal.