1

I have an ASP.NET Core Web application that has an interface in the application that inherits a class from the interface. I am trying to use the interface by dependency injection in the controller constructor, but I always get the following error

An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve service for type 'DependenceInjection_Dapper.Services.SendSMS' while attempting to activate 'DependenceInjection_Dapper.Controllers.HomeController'. Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)

The interface codes are as follows:

public interface IsmsSender
{
    string sendSms();
}

The class codes are as follows:

public class SendSms : IsmsSender
{
    public string sendSms()
    {
        return "send sms";
    }
}

And the following code is added in the program.cs file:

builder.Services.AddTransient<IsmsSender, SendSms>();

Also, the manufacturer of the controller is as follows:

public class HomeController : Controller
{
    private readonly IsmsSender _smsSender;

    public HomeController(SendSms smsSender)
    {
        _smsSender = smsSender;
    }

    public IActionResult Index()
    {
        ViewBag.send = _smsSender.sendSms();
        return View();
    }
}

However, I always get an error.

I behaved exactly according to the Microsoft documentation, but the problem was not solved.

2 Answers 2

2

You are injecting the concrete type instead of the interface, which is what you registered. Do this instead:

public class HomeController : Controller
{
    private readonly IsmsSender _smsSender;

    public HomeController(IsmsSender smsSender)
    {
        _smsSender = smsSender;
    }

    public IActionResult Index()
    {
        ViewBag.send = _smsSender.sendSms();
        return View();
    }
}

Always keep in mind that what matters for the container is the "registration type", not the concrete type. What this line says:

builder.Services.AddTransient<IsmsSender, SendSms>();

Is basically:

Whenever someone asks for an IsmsSender, give a SendSms instance to them

Nothing is said about consumers asking for SendSms.

It is possible to register the concrete type itself, though that's not usual and not recommended when you already have an abstraction in place: you want to rely on abstractions instead of concrete classes to reduce coupling in your implementation and make it more testable.

To register the concrete class itself, you'd just omit the first generic parameter:

builder.Services.AddTransient<SendSms>();

This now means that people must ask for SendSms directly, and IsmsSender won't be resolvable anymore.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, it helped a lot and it was completely correct, my problem was solved
-1

The problem comes from your consturctor

public HomeController(SendSms smsSender) { _smsSender = smsSender; }

should be

 public HomeController(ISendSms smsSender)
    {
        _smsSender = smsSender;
    }

you registred your ISmendSms as Sendsms in the depenency injection phase.

1 Comment

Thank you, your answer was completely correct

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.