dotnetdevcsharp
dotnetdevcsharp

Reputation: 3980

Unable to resolve service for type

I have an interface to a send mail async function which I am using for my email functions in my controller class.

private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IEmailSender _emailSender;

public AccountController(UserManager<ApplicationUser> userManager,
                         SignInManager<ApplicationUser> signInManager,
                         IEmailSender emailSender)
{
        _userManager = userManager;
        _signInManager = signInManager;
        _emailSender = emailSender;
}

As you see I am using the IEmailSender emailSender to create the object and setting it to its instance in the routine AccountController.

The interface is simply made up of one constructor

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace solitude.admin.core.Interfaces
{
    public interface IEmailSender
    {
        Task SendEmailAsync(string email, string subject, string message);
    }
}

But the problem is when I come to view my view I get the following error:

InvalidOperationException: Unable to resolve service for type 'solitude.admin.core.Interfaces.IEmailSender' while attempting to activate 'solitude.admin.core.Controllers.AccountController'.
Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)

Upvotes: 1

Views: 2421

Answers (2)

dotnetdevcsharp
dotnetdevcsharp

Reputation: 3980

Tim was indeed correct what I had to do was add this following code to my configure startup.cs

services.AddTransient<IEmailSender, AuthMessageSender>();

The class AuthMessageSender is made up of as follows.

// This class is used by the application to send Email and SMS
// when you turn on two-factor authentication in ASP.NET Identity.
// For more details see this link http://go.microsoft.com/fwlink/?LinkID=532713
public class AuthMessageSender : IEmailSender 
{
   public Task SendEmailAsync(string email, string subject, string message)
   {
            // Plug in your email service here to send an email.
            return Task.FromResult(0);
    }         
}

This allowed me to call the function from the class as normal I guess old .net new how to handle this can someone explain to me why this has changed in core why do we have to hard wire like this.

Upvotes: 0

Tim
Tim

Reputation: 6060

You need to register how the DI engine will provide an IEmailSender. Assuming you are using asp.net core, you do this is in your Startup.cs in the ConfigureServices method:

public void ConfigureServices(IServiceCollection services) {
   ...
   services.AddSingleton<IEmailSender, EmailSenderImplementation>();
   ...
}

This is where EmailSenderImplementation is a class that implements the IEmailSender interface.

This registration tells the DI framework how to get an implementation of IEmailSender. In my example I am telling it to instantiate a single instance of EmailSenderImplementation and reuse that instance over the lifetime of the application. You might need to use AddTransient (if you want a new one every time you ask for one) or AddScoped (if you want a new one for each http request) instead of AddSingleton depending on how your implementation of IEmailSender works.

Upvotes: 2

Related Questions