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 应用程序。
我觉得这其中的一些内容应该对你有所帮助,如果我指出的地方不正确,请指正我。
我正在使用 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 应用程序。
我觉得这其中的一些内容应该对你有所帮助,如果我指出的地方不正确,请指正我。