Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Core 2.0 Autofac Register Class InstancePerRequest doesn't work

Here is my interface

public interface IMatchServices
{
    string MatchList();
}

and class here

public class MatchServices : IMatchServices
{
    public string MatchList() {

        return "test";
    }
}

Controller

public class SearchController : Controller
{
    private readonly IMatchServices matchservices;

    public SearchController(IMatchServices matchservices)
    {
        this.matchservices = matchservices;
    }

    [Route("matchlist")]
    public string MatchList() {

        return matchservices.MatchList();
    }
}

and ConfigureService

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterType<MatchServices>().As<IMatchServices>().SingleInstance();
    builder.Populate(services);
    var container = builder.Build();
    return container.Resolve<IServiceProvider>();
}

And Finally The Error (When I register with InstancePerRequest):

Autofac.Core.DependencyResolutionException: Unable to resolve the type 'xxx.Services.MatchServices' because the lifetime scope it belongs in can't be located. The following services are exposed by this registration: - xxx.Interfaces.IMatchServices

Details ---> No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.

If you see this during execution of a web application, it generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario). Under the web integration always request dependencies from the dependency resolver or the request lifetime scope, never from the container itself. (See inner exception for details.) ---> Autofac.Core.DependencyResolutionException: No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.

When I register MatchServices class SingleInstance it is working but InstancePerRequest didn't work. Why? I didn't even do any DI in MatchServices.

like image 950
sonertbnc Avatar asked Feb 09 '18 12:02

sonertbnc


1 Answers

As per the Autofac documentation:

Use InstancePerLifetimeScope instead of InstancePerRequest. In previous ASP.NET integration you could register a dependency as InstancePerRequest which would ensure only one instance of the dependency would be created per HTTP request. This worked because Autofac was in charge of setting up the per-request lifetime scope. With the introduction of Microsoft.Extensions.DependencyInjection, the creation of per-request and other child lifetime scopes is now part of the conforming container provided by the framework, so all child lifetime scopes are treated equally - there’s no special “request level scope” anymore. Instead of registering your dependencies InstancePerRequest, use InstancePerLifetimeScope and you should get the same behavior. Note if you are creating your own lifetime scopes during web requests, you will get a new instance in these child scopes.

Also, you have another issue:

Note that Populate is basically a foreach to add things into Autofac that are in the collection. If you register things in Autofac BEFORE Populate then the stuff in the ServiceCollection can override those things; if you register AFTER Populate those registrations can override things in the ServiceCollection. Mix and match as needed.

In other words, you also have these lines in the wrong order:

builder.Populate(services);
builder.RegisterType<MatchServices>().As<IMatchServices>().InstancePerLifetimeScope();
like image 145
NightOwl888 Avatar answered Nov 14 '22 05:11

NightOwl888