Search code examples
c#restasp.net-corecqrsmediatr

no implicit reference conversion from 'System.Collections.Generic.List<Create.Command>' to 'MediatR.IRequest<MediatR.Unit>' + .NET Core + CQRS


I'm getting a List in the API controller method and passing it to the Handler like below. What I am intending to do is loop over the list and save all the items of the list into the DB.

public class Create
{
    public class Command : IRequest
    {
        public Guid A { get; set; }
        public string B { get; set; }
        public string C { get; set; }
        public bool D { get; set; }
    }

    public class Handler : IRequestHandler<List<Command>>
    {
        private readonly DataContext _context;
        private readonly IMapper _mapper;
        public Handler(DataContext context, IMapper mapper)
        {
            _mapper = mapper;
            _context = context;
        }

        public async Task<Unit> Handle(List<Command> request, CancellationToken cancellationToken)
        {
            // loop over the request list and save in the database
        }
    }
}

However there's a red line under 'Handler' in the code line: public class Handler : IRequestHandler<List<Command>>.

Hovering over the 'Handler', it says:

The type 'System.Collections.Generic.List' cannot be used as type parameter 'TRequest' in the generic type or method 'IRequestHandler'. There is no implicit reference conversion from 'System.Collections.Generic.List' to 'MediatR.IRequest'. [Application]csharp(CS0311)

My API Controller method is:

[HttpPost]
public async Task<ActionResult<Unit>> Create(List<Create.Command> commands) // not like this, it'll be a list
{
     return await Mediator.Send(commands);
}

Red Line under return await Mediator.Send(commands); says:

Cannot implicitly convert type 'object' to 'Microsoft.AspNetCore.Mvc.ActionResult'. An explicit conversion exists (are you missing a cast?) [API]csharp(CS0266)

If I've missed some information while writing the question, please be easy on me, I will keep updating upon inquiry.


Solution

  • So here's how I eventually solved the problem:

    Step 1: Instead of having props in the Command class, Have a nested class in the same Create.cs class where Command class is:

        public class CreateDto
        {
            public Guid A { get; set; }
            public string B { get; set; }
            public string C { get; set; }
            public bool D { get; set; }
        }
    

    Step 2: will be Command class. Command class will be now:

        public class Command : IRequest
        {
            public List<CreateDto> SomeObjects { get; set; }
        }
    

    Step 3: Handler class will become:

    public class Handler : IRequestHandler<Command>
        {
            private readonly DataContext _context;
            private readonly IMapper _mapper;
            public Handler(DataContext context, IMapper mapper)
            {
                _mapper = mapper;
                _context = context;
            }
    
            public async Task<Unit> Handle(Command request, CancellationToken cancellationToken)
            {
                foreach (var obj in request.SomeObjectss)
                {
                    // logic
                }
                return Unit.Value;
            }
        }
    

    Step 4: Controller method will become:

        [HttpPost]
        public async Task<ActionResult<Unit>> Create(List<CreateDto> createDtos)
        {
            return await Mediator.Send(new Create.Command{SomeObjects = createDtos});
        }