ASP.NET Core Web API + react js, .AspNetCore.Session 每次操作后变化

ASP.NET Core Web API + react js, .AspNetCore.Session changes after each action

我正在使用 ASP.NET Core Web API 制作购物车并做出反应。当测试在 Swagger UI 和 Postman 中所做的事情时,一切正常,但是当切换到 React 时,问题就开始了。每次我在 swagger/postman 中添加产品时,所有产品都会添加与当前会话相关的 ShoppingCartId。但是当我用 React 测试它时,每次添加产品后都会创建一个新的 ShoppingCartId,这是不应该发生的。下面是代码和结果:

Result in DB

会话配置:

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; 
        });

购物车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();
    }
}

控制器:

[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));
    }
}

反应

 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)
    }
}

更新:我认为问题在于,在 React 中,每次操作后都会生成一个新会话,而这在 Swagger 中不会发生。这可能是什么原因以及如何解决?

下面是修改后的静态会话截图:

.AspNetCore.Session React

.AspNetCore.Session React

.AspNetCore.Session Swagger

.AspNetCore.Session Swagger

我相信在将商品放入购物车之前,您会通过 get-shopping-cart 方法获得购物车。您可以在此处包含购物车的 Id 并将其设置在前端的某个位置,然后您可以将 productId 和 cartId 传递给 add-item-to-cart 端点并让您的 cartId 始终包含在请求中。

我还发现了这个 What is the best way to manage a user's session in React? 问题,它也可能对您有所帮助。

顺便说一句。在 GetShoppingCart 方法中,您将其称为 cardId 而不是 carrId> 没有打错字吗?

您可以删除 app.UseCookiePolicy()。此条目将阻止 cookie,直到您确认您同意接收它们。同时提供您的 cookie 名称 options.Cookie.Name = "YourName"。在options.Cookie.HttpOnly = true中需要将值改为false,否则浏览器将无法读取cookie。还要指定 options.Cookie.SameSite = SameSiteMode.None 以将 cookie 设置为您的 React 应用程序。

我觉得这其中的一些内容应该对你有所帮助,如果我指出的地方不正确,请指正我。