I'm making a shopping cart using ASP.NET Core Web API and react. When testing what was done in Swagger UI and Postman, everything works correctly, but when switching to react, problems begin. Each time when I add product in swagger/postman, all products are added with their ShoppingCartId
that is related to the current session. But when I tested it with React, after each added product a new ShoppingCartId
is created, which shouldn't happen. Below is the code and result:
Session Configuration:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped(sc => ShoppingCart.GetShoppingCart(sc));
services.AddDistributedMemoryCache();
services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(3600);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
ShoppingCart class:
public class ShoppingCart
{
public AppDbContext _context { get; set; }
public string ShoppingCartId { get; set; }
public List<ShoppingCartItem> ShoppingCartItem { get; set; }
public ShoppingCart(AppDbContext context)
{
_context = context;
}
public static ShoppingCart GetShoppingCart (IServiceProvider services)
{
ISession session = services.GetRequiredService<IHttpContextAccessor>()?.HttpContext.Session;
var context = services.GetService<AppDbContext>();
string cardId = session.GetString("CardId") ?? Guid.NewGuid().ToString();
session.SetString("CardId", cardId);
return new ShoppingCart(context) { ShoppingCartId = cardId };
}
public List<ShoppingCartItem> GetShoppingCartItems()
{
return ShoppingCartItem ?? (ShoppingCartItem = _context.ShoppingCartItem.Where(n => n.ShoppingCartId ==
ShoppingCartId).Include(n => n.Book).ToList());
}
public void AddItemToCart(Book book)
{
var shoppingCartItem = _context.ShoppingCartItem.FirstOrDefault(n => n.Book.Id == book.Id &&
n.ShoppingCartId == ShoppingCartId);
if(shoppingCartItem == null)
{
shoppingCartItem = new ShoppingCartItem()
{
ShoppingCartId = ShoppingCartId,
Book = book,
Amount = 1
};
_context.ShoppingCartItem.Add(shoppingCartItem);
}
else
{
shoppingCartItem.Amount ;
}
_context.SaveChanges();
}
}
Controller:
[Route("api/[controller]")]
[ApiController]
public class OrderController : ControllerBase
{
private readonly ShoppingCart _shoppingCart;
private readonly IOrderService _orderService;
public OrderController(ShoppingCart shoppingCart, IOrderService orderService)
{
_shoppingCart = shoppingCart;
_orderService = orderService;
}
[HttpGet("get-shopping-cart")]
public IActionResult GetShoppingCart()
{
var items = _shoppingCart.GetShoppingCartItems();
_shoppingCart.ShoppingCartItem = items;
var responce = new ShopCartVM()
{
ShoppingCartItem = items,
ShopCartTotal = _shoppingCart.GetShoppingCartTotal(),
TotalItems = _shoppingCart.GetShoppingCartItemsSummary()
};
return Ok(responce);
}
[HttpPost("add-item-to-cart")]
public async Task<IActionResult> AddItemToShoppingCart(int id)
{
var item = await _bookService.GetByIdShopAsync(id);
if (item != null)
{
_shoppingCart.AddItemToCart(item);
}
return RedirectToAction(nameof(GetShoppingCart));
}
}
React
export const addProduct = (productId: number) => async (dispatch: AppDispatch) => {
try {
const request = new XMLHttpRequest();
request.open("POST", `https://localhost:44307/api/Order/add-item-to-cart?id=${productId}`)
request.responseType = "text"
request.onload = function () {
const response = request.response;
console.log(response)
};
request.send();
} catch (e) {
console.log(e)
}
}
Update: I think the problem is that in React a new session is generated after each action, which does not happen in Swagger. What could be the reason for this and how to fix it?
Below is the screenshots with changes and static session:
CodePudding user response:
You can remove app.UseCookiePolicy()
. This entry will block cookies until you confirm that you agree to receive them. Also provide your cookie name options.Cookie.Name = "YourName"
. In options.Cookie.HttpOnly = true
, you need to change the value to false
, otherwise the browser will not be able to read the cookie. Also specify options.Cookie.SameSite = SameSiteMode.None
to set the cookie to your react app.
I think that something among all this should help you, correct me if I have indicated something incorrectly.
CodePudding user response:
I do believe that before you put an item to your cart you obtain a cart from the get-shopping-cart
method. You can contain here Id of the shopping cart and set it somewhere on your frontend side, then you can pass productId and cartId to a add-item-to-cart
endpoint and have your cartId always contained in the request.
Also I found this What is the best way to manage a user's session in React? question which may help you as well.
Btw. On the GetShoppingCart
method you call it cardId
instead of carrId
> Don't you have a typo?