I'm very new to ASP.NET Web API and I'm trying to use Entity Framework Core's Dependency Injection to POST data to the API Controller using MediatR pattern. But every time I run my code and it opens Swagger UI, I get an error 500 response saying
Unable to cast object of type 'AsyncStateMachineBox
1[System.Threading.Tasks.VoidTaskResult,S3E1.Repository.CartItemRepository <Createitem>d__5]' to type 'System.Threading.Tasks.Task
1[S3E1.Entities.CartItemEntity]'.
First, I added Dependency Injections to Program.cs
//Dependency Injection
builder.Services.AddDbContext<AppDataContext>(contextOptions => contextOptions.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")
));
//Connection
builder.Services.AddSingleton<DataConnectionContext>();
These are the classes. AppDataContext.cs
public class AppDataContext : DbContext
{
public AppDataContext(DbContextOptions<AppDataContext> contextOptions) : base(contextOptions) { }
public DbSet<CartItemEntity> CartItems { get; set; }
public DbSet<OrderEntity> Orders { get; set; }
public DbSet<UserEntity> Users{ get; set; }
}
DataConnectionContext.cs
public class DataConnectionContext
{
private readonly IConfiguration _configuration;
private readonly string _connectionString;
public DataConnectionContext(IConfiguration configuration)
{
_configuration = configuration;
_connectionString = _configuration.GetConnectionString("DefaultConnection");
}
public IDbConnection CreateConnection() => new SqlConnection(_connectionString);
}
Next is making a repository which holds the interface that has the create method.
public interface ICartItemRepository
{
//public Task<IEnumerable<CartItemEntity>> GetCartItems();
//public Task<CartItemEntity> GetCartItemEntity(Guid id);
public Task Createitem(CartItemEntity itemEntity);
}
Then a class that inherits the interface and calls the dependency constructors
public class CartItemRepository : ICartItemRepository
{
private readonly DataConnectionContext _connectionContext;
private readonly AppDataContext _appDataContext;
public CartItemRepository(DataConnectionContext connectionContext, AppDataContext appDataContext)
{
_connectionContext = connectionContext;
_appDataContext = appDataContext;
}
public async Task Createitem(CartItemEntity itemEntity)
{
_appDataContext.CartItems.Add(itemEntity);
await _appDataContext.SaveChangesAsync();
await _appDataContext.CartItems.ToListAsync();
}
}
Next is a command for POST request MediatR pattern
public record AddCartItemCommand(CartItemEntity cartItem) : IRequest<CartItemEntity>;
and a Handler which manages and returns the method createitem
public class AddItemsHandler : IRequestHandler<AddCartItemCommand, CartItemEntity>
{
private readonly ICartItemRepository _cartItemRepository;
public AddItemsHandler(ICartItemRepository cartItemRepository) => _cartItemRepository = cartItemRepository;
public async Task<CartItemEntity> Handle(AddCartItemCommand request, CancellationToken cancellationToken)
{
return await (Task<CartItemEntity>) _cartItemRepository.Createitem(request.cartItem);
}
}
and lastly, in the controller
[Route("api/cart-items")]
[ApiController]
public class CartItemsController : ControllerBase
{
private ISender _sender;
public CartItemsController(ISender sender) => _sender = sender;
[HttpPost]
public async Task<CartItemEntity> Post(CartItemEntity cartItemEntity)
{
return await _sender.Send(new AddCartItemCommand(cartItemEntity));
}
}
I tried modifying the return object in the handler but every time I change anything it always get the error squiggly line, so I just casted the (Task) after the await. Is this where I went wrong? Thank you for any answers.
CodePudding user response:
The exception is clear. You can't cast a VoidTaskResult
to Task<CartItemEntity>
.
To solve the problem:
In
ICartItemRepository
, modify the return type forCreateitem
asTask<CartItemEntity>
.In
CartItemRepository
, implementCreateitem
method from theICartItemRepository
interface. Return the inserteditemEntity
in the method.Since you have implemented
Task<CartItemEntity> Createitem(CartItemEntity itemEntity)
in theICartItemRepository
interface, the casting to(Task<CartItemEntity>)
is no longer needed, and suggested to be removed.
public interface ICartItemRepository
{
...
public Task<CartItemEntity> Createitem(CartItemEntity itemEntity);
}
public class CartItemRepository : ICartItemRepository
{
...
public async Task<CartItemEntity> Createitem(CartItemEntity itemEntity)
{
_appDataContext.CartItems.Add(itemEntity);
await _appDataContext.SaveChangesAsync();
return itemEntity;
}
}
public class AddItemsHandler : IRequestHandler<AddCartItemCommand, CartItemEntity>
{
...
public async Task<CartItemEntity> Handle(AddCartItemCommand request, CancellationToken cancellationToken)
{
return await _cartItemRepository.Createitem(request.cartItem);
}
}