Dninja
Dninja

Reputation: 109

Getting an InvalidOperationException when using a concrete class as a Controller property .NET Core

When passing MailService to my Controller's constructor my app throws a System.InvalidOperationException. However, when I switch it out for the interface, it works. What is the reason for this?

In Startup.cs

services.AddScoped<IMailService, MailService>();

In my Controller

private IMailService MailService { get; }

public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, MailService mailService)
{
    if (userManager == null)
        throw new ArgumentNullException(nameof(userManager));

    if (signInManager == null)
        throw new ArgumentNullException(nameof(signInManager));

    if (mailService == null)
        throw new ArgumentNullException(nameof(mailService));

    this.UserManager = userManager;
    this.SignInManager = signInManager;
    this.MailService= mailService;
}

Many thanks!

Upvotes: 0

Views: 97

Answers (2)

Igor
Igor

Reputation: 62238

services.AddScoped<IMailService, MailService>();

Because of that line. You are telling the DI service to inject an instance of MailService in the constructors when it encounters a parameter in the constructor of type IMailService.

You have nothing defined for injecting (replacing) instances of type MailService.

What you have now is good practice, do not change it. You want to program against interfaces when possible. This is also called interface based programming and there are many benefits.


See also a possibly related question: What does it mean to "program to an interface"?

Upvotes: 2

Jonesopolis
Jonesopolis

Reputation: 25370

I noticed this too. Back when we used Unity for DI, it would be fine with resolving a concrete class you requested, even if you had not specifically added it to the container.

With .NET Core dependency injection, it requires that you specifically declare the services you are injecting. Even though it could resolve your concrete class, I'm guessing the decision was made at some point in the development process to require this. So your code would work if you did:

services.AddScoped<MailService>();

Upvotes: 0

Related Questions