Search code examples
c#asp.net-coredependency-injectiondto

Unable to resolve service for type when mapping


I'm having trouble mapping to the data from my model to my modelDto (in the below example its labelled as state due to internal code practices at my workplace)

however when I try to run program and call my endpoint, i receive the following error:

Unable to resolve service for type 'project1.API.Core.Mappers.Interfaces.IMapToNew`2[Project1.API.Features.Personalisation.Personalisation,Project1.API.Features.Personalisation.Responses.PersonalisationState]' while attempting to activate 'Project1.API.Features.Personalisation.Services.PersonalisationBogusService'.

Think its a problem with how I am mapping the data, but I can't spot the problem. I'll post all the relevant classes for an overview.

public static class ServiceCollectionExtensions
{
public static void GetPersonalisationFeature(this IServiceCollection serviceCollection, IConfiguration config)
{
    config.ThrowIfNull(nameof(config));

    serviceCollection.AddScoped<IPersonalisationService, PersonalisationBogusService>();
}

}

class PersonalisationToPersonalisationState : IMapToNew<Personalisation, PersonalisationState>
{
    public PersonalisationState Map(Personalisation model)
    {
        return new PersonalisationState
        {
            UserType = EnumExtensions.StringToEnum(model.UserType, UserType.Student),
            UserRole = EnumExtensions.StringToEnum(model.UserRole, UserRole.PrimaryGuest),
            BookingPeriod = EnumExtensions.StringToEnum(model.BookingPeriod, BookingPeriod.PreCheckin)
        };
    }
}

public class Personalisation
{
    public string UserType { get; set; }

    public string UserRole { get; set; }

    public string BookingPeriod { get; set; }
}


 public class PersonalisationState
{
    [Description("Get user type based on userID")]
    public UserType UserType { get; set; }
    [Description("Get user role based on userID")]
    public UserRole UserRole { get; set; }
    [Description("Get the booking period of a user based on UserID")]
    public BookingPeriod BookingPeriod { get; set; }
}

public interface IPersonalisationService
{
    Task<IEnumerable<PersonalisationState>> GetPersonalisation(string Id);
}

public class PersonalisationBogusService : IPersonalisationService
{
    private readonly IMapToNew<Personalisation, PersonalisationState> _mapper;


    public PersonalisationBogusService(IMapToNew<Personalisation, PersonalisationState> mapper)
    {
        _mapper = mapper;
    }

    public async Task<IEnumerable<PersonalisationState>> GetPersonalisation(string Id)
    {
        var personalise = GetMockData();
        personalise.Add(GetFakePersonalisedData());
        return personalise
            .Select(b => _mapper.Map(b))

            .Select(b =>
            {
                b.UserType = UserType.Student;
                return b;
            })
            .Select(b =>
            {
                b.UserRole = UserRole.PrimaryGuest;
                return b;
            })
            .Select(b =>
            {
                b.BookingPeriod = BookingPeriod.PreCheckin;
                return b;
            });


    }


    private Personalisation GetFakePersonalisedData()
    {
        return new Personalisation
        {
            UserType = "Student",
            UserRole = "PrimaryGuest",
            BookingPeriod = "01/01/2019"
        };
    }

    public static List<Personalisation> GetMockData()
    {
        return new List<Personalisation> {new Personalisation {UserType = "", UserRole = "", BookingPeriod = ""}};

    }

}

public class PersonalisationController : BaseController
{
    private readonly IPersonalisationService _personalisationService;

    public PersonalisationController(IPersonalisationService personalisationService)
    {
        _personalisationService = personalisationService;
    }


    public async Task<ActionResult> Get([Description("Determines groups a user belongs to via their ID")] string id)
    {
        var result = await _personalisationService.GetPersonalisation(id);
        return Ok(result);
    }

}

and yes, I have also added the relevant code in the startup.cs file:

services.GetPersonalisationFeature(_configuration);


Solution

  • Target service expects IMapToNew<Personalisation, PersonalisationState> but based on the exception, that type has not been registered with the service collection.

    Make sure that all dependent types are added to the service collection.

    public static class ServiceCollectionExtensions {
        public static void GetPersonalisationFeature(this IServiceCollection serviceCollection, IConfiguration config) {
            config.ThrowIfNull(nameof(config));
    
            serviceCollection.AddScoped<IMapToNew<Personalisation, PersonalisationState>, PersonalisationToPersonalisationState>();
            serviceCollection.AddScoped<IPersonalisationService, PersonalisationBogusService>();
        }
    }
    

    So that they can be resolved when activating dependent classes.

    Consider creating a derived type

    public interface IPersonalisationToPersonalisationState 
        : IMapToNew<Personalisation, PersonalisationState> { }
    
    public class PersonalisationToPersonalisationState : IPersonalisationToPersonalisationState {
        //...omitted for brevity
    }
    

    Updating the service constructor

    public class PersonalisationBogusService : IPersonalisationService {
        private readonly IMapToNew<Personalisation, PersonalisationState> _mapper;
    
    
        public PersonalisationBogusService(IPersonalisationToPersonalisationState mapper) {
            _mapper = mapper;
        }
    
        //...omitted for brevity
    }
    

    And making sure to register the new abstraction

    public static class ServiceCollectionExtensions {
        public static void GetPersonalisationFeature(this IServiceCollection serviceCollection, IConfiguration config) {
            config.ThrowIfNull(nameof(config));
    
            serviceCollection.AddScoped<IPersonalisationToPersonalisationState, PersonalisationToPersonalisationState>();
            serviceCollection.AddScoped<IPersonalisationService, PersonalisationBogusService>();
        }
    }