Home > Blockchain >  ASP.NET Core - System.InvalidOperationException: Unable to resolve service for type while attempting
ASP.NET Core - System.InvalidOperationException: Unable to resolve service for type while attempting

Time:12-03

In my ASP.NER Core Web API Project, I have this code:

public interface IUriPaginationService
{
    public Uri GetPaginationUri(int page, string actionUrl);
}

public class UriPaginationService : IUriPaginationService
{
    private readonly string _baseUri;
    public UriPaginationService(string baseUri)
    {
        _baseUri = baseUri;
    }
    public Uri GetPaginationUri(int page, string actionUrl)
    {
        string baseUrl = $"{_baseUri}{actionUrl}";
        return new Uri(baseUrl);
    }
}

public abstract class AuditableBaseEntity
{
    public AuditableBaseEntity()
    {
        CreatedDate = DateTime.Now;
    }

    [Key]
    public virtual long Id { get; set; }

    [JsonIgnore]
    public bool IsDeleted { get; set; }

    [DataType(DataType.DateTime)]
    public DateTime? CreatedDate { get; set; }
    public long? LastUpdatedBy { get; set; }
}

Repositories:

public interface IBaseRepository<T> where T : AuditableBaseEntity
{

    Task<IEnumerable<T>> GetAll();
    Task<T> GetById(long id);
    bool EntityExists(long id);
}

public class BaseRepository<T> : IBaseRepository<T> where T : AuditableBaseEntity
{
    private readonly DDMDbContext _context;
    private DbSet<T> _entities;

    public BaseRepository(DDMDbContext context)
    {
        _context = context;
        _entities = context.Set<T>();
    }

    public async Task<IEnumerable<T>> GetAll()
    {
        var list = await _entities.Where(x => x.IsDeleted == false).ToListAsync();
        return list;
    }

    public async Task<T> GetById(long id)
    {
        return await _entities.FindAsync(id);
    }

    public bool EntityExists(long id)
    {
        return _entities.Any(x => x.Id == id && x.IsDeleted == false);
    }
}

UnitOfWork:

public interface IUnitOfWork : IDisposable
{
    IBaseRepository<Merchant> MerchantRepository { get; }
}

public class UnitOfWork : IUnitOfWork
{
    private readonly DDMDbContext _context;

    public UnitOfWork(DDMDbContext context)
    {
        _context = context;
    }

    private readonly IBaseRepository<Merchant> _merchantRepository;
    public IBaseRepository<Merchant> MerchantRepository => _merchantRepository ?? new BaseRepository<Merchant>(_context);

    public void Dispose()
    {
        if (_context != null)
        {
            _context.Dispose();
        }
    }
}

Services:

public interface IMerchantService
{
    public Task<IEnumerable<Merchant>> GetMerchants();
    public bool EntityExists(long id);
    public Task<ResponsePagination<GenericPagination<MerchantGetDto>>> GetAll(int page, int sizeByPage);
}


public class MerchantService : IMerchantService
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly IUriPaginationService _uriPaginationService;
    private readonly DDMDbContext _context;

    public MerchantService(IUnitOfWork unitOfWork, IUriPaginationService uriPaginationService, DDMDbContext context)
    {
        _unitOfWork = unitOfWork;
        _uriPaginationService = uriPaginationService;
        _context = context;
    }
    public async Task<IEnumerable<Merchant>> GetMerchants()
    {
        return await _unitOfWork.MerchantRepository.GetAll();
    }
    public async Task<ResponsePagination<GenericPagination<MerchantGetDto>>> GetAll(int page, int sizeByPage)
    {
        string nextRoute = null, previousRoute = null;
        IEnumerable<Merchant> data = await _unitOfWork.MerchantRepository.GetAll();

        var mapper = new EntityMapper();
        var merchantsDto = data.Select(m => mapper.FromMerchantToMerchantGetDto(m)).ToList();

        GenericPagination<MerchantGetDto> objGenericPagination = GenericPagination<MerchantGetDto>.Create(merchantsDto, page, sizeByPage);
        ResponsePagination<GenericPagination<MerchantGetDto>> response = new ResponsePagination<GenericPagination<MerchantGetDto>>(objGenericPagination);
        response.CurrentPage = objGenericPagination.CurrentPage;
        response.HasNextPage = objGenericPagination.HasNextPage;
        response.HasPreviousPage = objGenericPagination.HasPreviousPage;
        response.PageSize = objGenericPagination.PageSize;
        response.TotalPages = objGenericPagination.TotalPages;
        response.TotalRecords = objGenericPagination.TotalRecords;
        response.Data = objGenericPagination;

        if (response.HasNextPage)
        {
            nextRoute = $"/merchants?page={(page   1)}";
            response.NextPageUrl = _uriPaginationService.GetPaginationUri(page, nextRoute).ToString();
        }
        else
        {
            response.NextPageUrl = null;
        }

        if (response.HasPreviousPage)
        {
            previousRoute = $"/merchants?page={(page - 1)}";
            response.PreviousPageUrl = _uriPaginationService.GetPaginationUri(page, previousRoute).ToString();
        }
        else
        {
            response.PreviousPageUrl = null;
        }

        return response;
    }

    public bool EntityExists(long id)
    {
        return _unitOfWork.MerchantRepository.EntityExists(id);
    }

    public async Task<Merchant> GetById(long id)
    {
        return await _unitOfWork.MerchantRepository.GetById(id);
    }
}

Controller:

[Produces("application/json")]
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class AdminController : ControllerBase
{
    private readonly IMerchantService _merchantService;

    public AdminController(MerchantService merchantService)
    {
        _merchantService = merchantService;
    }

    [HttpGet("merchants")]
    public async Task<ResponsePagination<GenericPagination<MerchantGetDto>>> GetAll(int page, int sizeByPage)
    {
        return await _merchantService.GetAll(page, sizeByPage);
    }
}

startup:

    public void ConfigureServices(IServiceCollection services)
    {
//        services.AddMvc();
        services.AddControllers();
        services.AddDb(Configuration);
        services.AddJwtAuthentication(Configuration);
        services.AddMvcCoreFramework(Configuration);
        services.AddAppAuthorization(Configuration);

        services.AddControllersWithViews();
        services.AddRazorPages();

        services.AddVersioning();

        services.AddSwagger();

        services.AddRouting(options => options.LowercaseUrls = true);

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddSingleton<IUriPaginationService>(provider =>
        {
            var accesor = provider.GetRequiredService<IHttpContextAccessor>();
            var request = accesor.HttpContext.Request;
            var absoluteUri = string.Concat(request.Scheme, "://", request.Host.ToUriComponent());
            return new UriPaginationService(absoluteUri);
        });

        services.AddScoped(typeof(IBaseRepository<>), typeof(BaseRepository<>));
        services.AddScoped<IUnitOfWork, UnitOfWork>();
        services.AddTransient<IMerchantService, MerchantService>();
    }

When I use this on postman get request:

https://localhost:44341/api/v1/merchant/mandates

I got this error:

System.InvalidOperationException: Unable to resolve service for type 'API.Infrastructure.Services.Concrete.MerchantService' while attempting to activate 'API.Web.Controllers.v1.MerchantController'. at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)

How do I resolve this:

Thanks

CodePudding user response:

The controller is dependent on the implementation (class)

public AdminController(MerchantService merchantService)
{
    _merchantService = merchantService;
}

while you registered the abstraction (interface).

services.AddTransient<IMerchantService, MerchantService>();

Based on the registration it is most likely the controller was meant to be dependent on the interface (abstraction)

public AdminController(IMerchantService merchantService) //<-- CHANGED TO INTERFACE
{
    _merchantService = merchantService;
}

Updating the controller constructor to be dependent on the registered abstraction will fix the shown exception.

  • Related