Search code examples
c#asp.net-coreasp.net-core-viewcomponent

ViewComponent not happy about my query


I'm struggeling to get a grasp on ViewComponents. I have this ViewComponent class for a shopping cart:

public class ShoppingCartViewComponent : ViewComponent
{
    private readonly MyStoreContext _context;

    public ShoppingCartViewComponent(MyStoreContext context)
    {
        _context = context;
    }

    public async Task<IViewComponentResult> InvokeAsync(int Id)
    {
        return View(await GetCartAsync(Id));
    }

    private Task<ViewModelShoppingCart> GetCartAsync(int Id)
    {
        var VMCart = _context.ShoppingCarts
                    .Where(c => c.Id == Id)
                    .Select(cart => new ViewModelShoppingCart
                    {
                        Id = cart.Id,
                        Title = cart.Title,
                        CreateDate = cart.CreateDate,
                        ShoppingCartItems = cart.ShoppingCartItems
                                            .Select(items => new ViewModelShoppingCartItem
                                            {
                                                ProductId = items.ProductId,
                                                ProductTitle = items.Product.Title,
                                                ProductPrice = items.Product.Price,
                                                Quantity = items.Quantity
                                            }).ToList()
                    }).FirstOrDefault();
        return VMCart;
    }
}

This causes a build error on return VMCart, with this message from VS:

Cannot implicitly convert type 'System.Linq.IQueryable<MyStore.Models.ViewModels.ViewModelShoppingCart>' to 'System.Threading.Tasks.Task<MyStore.Models.ViewModels.ViewModelShoppingCart>'. An explicit conversion exists (are you missing a cast?)

What am I doing wrong? EDIT Added .FirstOrDefault() at the end of my query, but the error remains the same.


Solution

  • The problem is that your function definition looks like you're trying to make an async method but nothing internally is async. Change it to this:

    private async Task<ViewModelShoppingCart> GetCartAsync(int Id)
    {
        var VMCart = await _context.ShoppingCarts
                    .Where(c => c.Id == Id)
                    .Select(cart => new ViewModelShoppingCart
                    {
                        Id = cart.Id,
                        Title = cart.Title,
                        CreateDate = cart.CreateDate,
                        ShoppingCartItems = cart.ShoppingCartItems
                                            .Select(items => new ViewModelShoppingCartItem
                                            {
                                                ProductId = items.ProductId,
                                                ProductTitle = items.Product.Title,
                                                ProductPrice = items.Product.Price,
                                                Quantity = items.Quantity
                                            }).ToList()
                    }).FirstOrDefaultAsync();
        return VMCart;
    }
    

    Or make it not async:

    private ViewModelShoppingCart GetCart(int Id)
    {
        var VMCart = _context.ShoppingCarts
                    .Where(c => c.Id == Id)
                    .Select(cart => new ViewModelShoppingCart
                    {
                        Id = cart.Id,
                        Title = cart.Title,
                        CreateDate = cart.CreateDate,
                        ShoppingCartItems = cart.ShoppingCartItems
                                            .Select(items => new ViewModelShoppingCartItem
                                            {
                                                ProductId = items.ProductId,
                                                ProductTitle = items.Product.Title,
                                                ProductPrice = items.Product.Price,
                                                Quantity = items.Quantity
                                            }).ToList()
                    }).FirstOrDefault();
        return VMCart;
    }