Muqeet Khan
Muqeet Khan

Reputation: 2114

Unable to get Scoped Service in aspnetcore 1 - RC1 to work

My scoped service for some reason seems to be generating different instances of the same class when I try to access it in 2 middlewares within the same request.

Scenario: I am adding a scoped service as such:

public interface ISimplyRecorder
    {
        void AddInfo(string key, string value);
        Dictionary<string, string> GetAllInfo();   
    }


public class SimplyCoreRecorderService : ISimplyRecorder
    {
        private Dictionary<string,string> data;

        public SimplyCoreRecorderService()
        {
            data = new Dictionary<string, string>();
        }

        public void AddInfo(string key,string value)
        {
            data.Add("",value);
        }

        public Dictionary<string,string> GetAllInfo()
        {
            return data;
        }

    }

and then the following in startup.cs

services.AddScoped<ISimplyRecorder,SimplyRecorderService>();

now I am calling this service in the constructor of a sample Middleware. I am able to access the service with a new instance and add data into it and then I call await _next(context). However, when I am calling the service in my HomeController, MVC which follows the middleware above, I seem to be getting a new instance of the service even though it's the same request.

HomeController:

ISimplyRecorder _simply;
private IHostingEnvironment _env;

public HomeController(IHostingEnvironment env,ISimplyRecorder simply)
{
    _simply = simply;
    _env = env;
}

public IActionResult Index()
{
    _simply.AddInfo("Home:Action","resulted in index action");
    return View();
}

complete code available at: https://github.com/muqeet-khan/SimplyCore if someone wants to give it a go.

Upvotes: 0

Views: 139

Answers (1)

Ricky
Ricky

Reputation: 10751

Middlewares are instantiated only once when it's first involved, then all the following requests are handled by that middleware instance. NOT a new middleware instance for each request.

You get your ISimplyRecorder in the constructor of the middleware and "cache" it as a private readonly variable. This means the middleware will get the ISimplyRecorder instance of the first request, then keep adding data to that instance for all the following requests rather than the new ISimplyRecorder instance for the following requests which you get in HomeController.

To solve it, you need to get ISimplyRecorder instance from the Invoke method of the middleware.

// using Microsoft.Extensions.DependencyInjection;
public async Task Invoke(HttpContext httpContext)
{
    ISimplyRecorder recoder = httpContext.RequestServices.GetRequiredService<ISimplyRecorder>();
}

EDIT:

The comment of Juergen is correct, I tried it out. You may also just write like this:

public async Task Invoke(HttpContext httpContext, ISimplyRecorder recorder)
{
    // recorder is from DI
}

Upvotes: 1

Related Questions