Я новичок в веб-API ASP.NET и пытаюсь использовать внедрение зависимостей Entity Framework Core для данных POST в контроллер API с использованием шаблона MediatR. Но каждый раз, когда я запускаю свой код и он открывает пользовательский интерфейс Swagger, я получаю ответ с ошибкой 500, говорящий
Не удалось преобразовать объект типа «AsyncStateMachineBox
1[System.Threading.Tasks.VoidTaskResult,S3E1.Repository.CartItemRepository+<Createitem>d__5]' to type 'System.Threading.Tasks.Task
1[S3E1.Entities.CartItemEntity]».
Во-первых, я добавил внедрение зависимостей в Program.cs.
//Dependency Injection
builder.Services.AddDbContext<AppDataContext>(contextOptions => contextOptions.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection")
));
//Connection
builder.Services.AddSingleton<DataConnectionContext>();
Это классы. 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);
}
Далее создается репозиторий, содержащий интерфейс с методом create.
public interface ICartItemRepository
{
//public Task<IEnumerable<CartItemEntity>> GetCartItems();
//public Task<CartItemEntity> GetCartItemEntity(Guid id);
public Task Createitem(CartItemEntity itemEntity);
}
Затем класс, который наследует интерфейс и вызывает конструкторы зависимостей
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();
}
}
Далее идет команда для шаблона MediatR запроса POST.
public record AddCartItemCommand(CartItemEntity cartItem) : IRequest<CartItemEntity>;
и обработчик, который управляет и возвращает метод 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);
}
}
и, наконец, в контроллере
[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));
}
}
Я попытался изменить возвращаемый объект в обработчике, но каждый раз, когда я что-либо меняю, он всегда получает волнистую строку с ошибкой, поэтому я просто применил (Task) после ожидания. Это где я ошибся? Спасибо за любые ответы.
Исключение понятно. Вы не можете бросить VoidTaskResult
на Task<CartItemEntity>
.
Решить проблему:
В ICartItemRepository
измените тип возвращаемого значения для Createitem
на Task<CartItemEntity>
.
В CartItemRepository
реализуйте метод Createitem
из интерфейса ICartItemRepository
. Верните вставленный itemEntity
в метод.
Поскольку вы реализовали Task<CartItemEntity> Createitem(CartItemEntity itemEntity)
в интерфейсе ICartItemRepository
, приведение к (Task<CartItemEntity>)
больше не нужно, и его предлагается удалить.
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);
}
}
Большое спасибо за это, недавно я только что изучил шаблоны MediatR, поэтому передача нескольких запросов и команд обработчикам сбивала с толку.