13

I'm trying to use in my ASP.NET Core 2.0 web app this sample RazorViewEngineEmailTemplates to create an html email body from View. But when I run it and my controller gets an ajax request, I get this error:

Cannot resolve scoped service Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.IViewBufferScope from root provider

It's probably coming from resolving dependencies in the RazorViewToStringRenderer class but I have no idea how to fix this.

skink
  • 5,133
  • 6
  • 37
  • 58
AlexB
  • 4,167
  • 4
  • 45
  • 117

2 Answers2

18

ok, the problem was I used renderer from a Singleton service (EmailerService). I changed its registration to Scoped and it all works now:

services.AddScoped<IEmailer, EmailerService>();
AlexB
  • 4,167
  • 4
  • 45
  • 117
7

When a service gets injected as scoped, the dependent class must also be injected as scoped.

Unfortunately, this does not work for every use case. When creating the E-Mail service statically, you don't have an HTTP Context.

In my case, I had a scheduled Task that was executed statically by Hangfire:

var mailer = ServiceProviderSinleton.Instance.GetService(typeof(IEmailer))

When you need that scoped service from a static context, you have two options:

  1. use a dependency injection framework that gives you more control over the injection context. I highly recommend DryIoc.Microsoft.DependencyInjection from NuGet. (Documentation)

  2. disable the scope validation:

return WebHost.CreateDefaultBuilder()
    .ConfigureLogging(builder => builder.AddSerilog(Log.Logger, dispose: true))
    .UseKestrel(options => options.ConfigureEndpoints(configuration))
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .UseStartup<TStartup>()
    .UseSerilog()
    .UseDefaultServiceProvider(options => options.ValidateScopes = false)
    .Build();
MovGP0
  • 7,267
  • 3
  • 49
  • 42
  • 2
    With ASP.NET Core 2.1 you can now create a scope manually: ```using Microsoft.Extensions.DependencyInjection; using(var scope = serviceProvider.CreateScope()) { var myScopedService = scope.ServiceProvider.GetService(); } ``` – olivierr91 May 15 '18 at 14:21
  • @MovGP0 Where does that code even go and I how do I force it to work? Do I need everything that you've set? Is it a replacement for something else? – Robert Burke May 15 '18 at 15:19
  • 1
    @RobertBurke, I think he's referring to a setup like this: https://stackoverflow.com/a/55381457/522859. I implemented that after hitting the same problem and it resolved it for me. – Chris Owens May 09 '20 at 06:24