-
Notifications
You must be signed in to change notification settings - Fork 259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Does not work with generic host #317
Comments
@twenzel There is not enough information here to reproduce the issue you're explaining. There is a ServiceCollectionExtensionsTest which covers using RazorLight with Microsoft DI. I'm not clear what code you wrote to get an InvalidOperationException - you gave me all the code except for the call site that triggers this exception. I'm also not sure why you're registering all these things as singletons after you call Build. The whole point of calling UseMemoryCachingProvider is so that it sets up the cache for when you call Build. |
@jzabroski this is happening for me also on aspnet core 3.1, you shouldn't really need much to reproduce it:
Trace:
|
@twenzel I digged into an older project that started in core 2.1 before migrating to 3.1, where Razorlight works! The difference is, which I hadn't noticed, that the working project uses |
I started cleaning this up. |
@georgiosd So, I would appreciate a repro. I spent an hour today figuring out if I could repro @twenzel or your problem, and I cannot. Below is an example of what I tried.
|
This workaround fixes it for me too. |
The workaround proposed by @twenzel only works for 2.0.0-beta4. The 2.0.0-rc.2 version throws:
There is a sample project: https://github.com/knuxbbs/RazorLightSample |
@jzabroski static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args).UseDefaultServiceProvider((context, options) =>
{
options.ValidateOnBuild = true;
}).ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<EmbeddedEngineStartup>(); });
} |
For 2.0.0-rc.2, what worked for me was registering public void ConfigureServices(IServiceCollection services)
{
var engine = new RazorLightEngineBuilder()
.UseEmbeddedResourcesProject(typeof(Startup))
.UseMemoryCachingProvider()
.Build();
services.AddSingleton(engine.Handler);
services.AddRazorLight(() => engine);
} |
@edvinklaebo - so, you're saying the following test is incorrect? RazorLight/tests/RazorLight.Tests/Extensions/ServiceCollectionExtensionsTest.cs Lines 80 to 100 in 4fb414a
I am not sure why I would need to call Or, did you mean to reply to @knuxbbs ? |
@edvinklaebo Hmm... I just updated the test and it looks like you're right. Why would |
@edvinklaebo I played around with your sample code and
Below is a brain dumpValidateOnBuild was introduced in .netcoreapp3.0 TFM, so it makes sense this would only have caused issues starting with .NET Core 3.x. |
I think I figured this out. The issue is that since we resolve the IEngineHandler from the RazorLightEngineBuilder call, the ValidateOnBuild cannot statically verify the contents of the lambda. The only way it can "know" that IEngineHandler cannot be resolved is because we told it about the dependency in the line before. TryAdd does what it's supposed to do, which is only register the engine handler if it hasn't already been provided. But, the static verification doesn't know that we've provided a concrete instance in the next registration. tl;dr: By eliminating this line, all tests pass: It appears I broke this, although I can't remember why I did this (it was almost certainly to handle a scenario where people do silly things like register RazorLight using the RazorLightEngineBuilder, but then call the EngineHandler interface directly), and I didn't submit a issue number along with the check-in. Is there any alternative to removing this line? |
I think the workaround is to fail hard if people try to call the engine handler directly after calling AddRazorLight: services.TryAddSingleton<IEngineHandler>(p =>
throw new InvalidOperationException($"This exception can only occur if you inject {nameof(IEngineHandler)} directly using {nameof(ServiceCollectionExtensions)}.{nameof(AddRazorLight)}")); This might break some people, but at least the reason is fairly clear. Feedback? Thoughts? Questions? Concerns? |
One last thought. I guess there could be an AddRazorLightEngineHandler() extension method for those that don't want RazorLightEngine. The exception message could then be updated to suggest a call to action to "Consider using AddRazorLightEngineHandler() instead." But that still has to deal with things RazorLightEngine bundles, like support for |
Describe the bug
InvalidOperationException: Unable to resolve service for type 'RazorLight.RazorLightOptions' while attempting to activate 'RazorLight.EngineHandler'.
To Reproduce
Steps to reproduce the behavior: Create a new ASP.NET Core 3.1 MVC application with the new generic host template
Add RazorLight to the services:
Exception:
InvalidOperationException: Unable to resolve service for type 'RazorLight.RazorLightOptions' while attempting to activate 'RazorLight.EngineHandler'.
Expected behavior
Runs smoothly.
The problem is that the
RazorLightOptions
are not registered which are required by theEngineHandler
.Workaround
Register missing dependencies separately
Information (please complete the following information):
The text was updated successfully, but these errors were encountered: