Home > Software engineering >  ASP.NET Core Web API react js, .AspNetCore.Session changes after each action
ASP.NET Core Web API react js, .AspNetCore.Session changes after each action

Time:04-25

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:

Result in DB

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:

.AspNetCore.Session React

.AspNetCore.Session React

.AspNetCore.Session Swagger

.AspNetCore.Session Swagger

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?

  • Related