Проблема с функциональностью ShoppingCart внутри моего проектаC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Проблема с функциональностью ShoppingCart внутри моего проекта

Сообщение Anonymous »

Сейчас я изучаю C# ASP.NET Core, это мой проект, над которым я работаю -> https://github.com/Slavilov/Bookshop-AS ... pplication,
У меня проблема с файлом ShoppingCartService.cs! Когда программы переходят к методу public async Task AddToCart(int bookId), он успешно добавляет товар в корзину, но когда он переходит к последней строке -> SaveShoppingCart(shoppingCart); я потеряю все?? Почему это? Извините за невежество, я был бы признателен, если бы кто-нибудь из вас объяснил, в чем моя ошибка, спасибо!

Код: Выделить всё

` public async Task AddToCart(int bookId)
{
var shoppingCart = GetShoppingCart();
var book = await _bookService.GetBookByIdAsync(bookId);
if (book == null) return;

var cartItem = shoppingCart.Items.FirstOrDefault(i => i.BookId == bookId);
if (cartItem == null)
{
shoppingCart.Items.Add(new CartItem { BookId = bookId, Book = book, Quantity = 1 });
}
else
{
cartItem.Quantity++;
}

SaveShoppingCart(shoppingCart);
}`
Я проверил, что сеанс зарегистрирован в Program.cs:
Я добавил builder.Services.AddSession(options =>

Код: Выделить всё

{ options.IdleTimeout = TimeSpan.FromMinutes(30); // Adjust as needed options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; });

Код: Выделить всё

`app.UseRouting();
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
`
Я убедился, что HttpContextAccessor правильно зарегистрирован в моем Program.cs ->

Код: Выделить всё

`builder.Services.AddHttpContextAccessor();`
Это весь мой код для ShoppiCartFunctionality ->
ShoppingCartController.cs ->

Код: Выделить всё

using Microsoft.AspNetCore.Mvc;

public class ShoppingCartController : Controller
{
private readonly IShoppingCartService _shoppingCartService;

public ShoppingCartController(IShoppingCartService
shoppingCartService)
{
_shoppingCartService = shoppingCartService;
}

public IActionResult CheckSession()
{
var testValue = HttpContext.Session.GetString("Test");
if (string.IsNullOrEmpty(testValue))
{
HttpContext.Session.SetString("Test", "Session is
working!");
}
return Content(HttpContext.Session.GetString("Test"));
}

public IActionResult Index()
{
var items = _shoppingCartService.GetCartItems();
var total = _shoppingCartService.GetCartTotal();

ViewBag.Items = items;
ViewBag.TotalPrice = total;

return View();
}

public IActionResult AddToCart(int bookId)
{
_shoppingCartService.AddToCart(bookId);
return RedirectToAction("Index");
}

public IActionResult RemoveFromCart(int bookId)
{
_shoppingCartService.RemoveFromCart(bookId);
return RedirectToAction("Index");
}

public IActionResult ClearCart()
{
_shoppingCartService.ClearCart();
return RedirectToAction("Index");
}
}
SessionExtensions.cs ->

Код: Выделить всё

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;

namespace SessionExtensions.Helpers
{
public static class SessionExtensions
{
public static void SetObjectAsJson(this ISession session, string key, object value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}

public static T GetObjectFromJson(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default(T) : JsonConvert.DeserializeObject(value);
}
}
}
ShoppingCart.cs ->

Код: Выделить всё

public class ShoppingCart
{
public List Items { get; set; } = new List();

public decimal GetTotalPrice()
{
return Items.Sum(item => item.Book.Price * item.Quantity);
}
}
IShoppingCartService.cs ->

Код: Выделить всё

public interface IShoppingCartService
{
Task AddToCart(int bookId);
void RemoveFromCart(int bookId);
void ClearCart();
List  GetCartItems();
decimal GetCartTotal();
}
ShoppingCartService.cs ->

Код: Выделить всё

using Bookshop_ASP.NET_Core_MVC_Application.Services;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using SessionExtensions.Helpers;
using System.Linq;
using System.Threading.Tasks;

public class ShoppingCartService : IShoppingCartService
{
private readonly IBookService _bookService;
private readonly IHttpContextAccessor _httpContextAccessor;
private const string CartSessionKey = "ShoppingCart";

public ShoppingCartService(IBookService bookService, IHttpContextAccessor httpContextAccessor)
{
_bookService = bookService;
_httpContextAccessor = httpContextAccessor;
}

public async Task AddToCart(int bookId)
{
var shoppingCart = GetShoppingCart();
var book = await _bookService.GetBookByIdAsync(bookId);
if (book == null) return;

var cartItem = shoppingCart.Items.FirstOrDefault(i => i.BookId == bookId);
if (cartItem == null)
{
shoppingCart.Items.Add(new CartItem { BookId = bookId, Book = book, Quantity = 1 });
}
else
{
cartItem.Quantity++;
}

SaveShoppingCart(shoppingCart);
}

public void RemoveFromCart(int bookId)
{
var shoppingCart = GetShoppingCart();
var cartItem = shoppingCart.Items.FirstOrDefault(i => i.BookId == bookId);
if (cartItem != null)
{
shoppingCart.Items.Remove(cartItem);
}

SaveShoppingCart(shoppingCart);
}

public void ClearCart()
{
var session = _httpContextAccessor.HttpContext?.Session;
if (session == null)
{
throw new InvalidOperationException("Session is not available.");
}
session.Remove(CartSessionKey);
}

public List GetCartItems()
{
return GetShoppingCart().Items;
}

public decimal GetCartTotal()
{
var shoppingCart = GetShoppingCart();
return shoppingCart.Items.Sum(i => i.Book.Price * i.Quantity);
}

private ShoppingCart GetShoppingCart()
{
var session = _httpContextAccessor.HttpContext?.Session;
if (session == null)
{
throw new InvalidOperationException("Session is not available.");
}
var cart = session.GetObjectFromJson(CartSessionKey) ?? new ShoppingCart();

//Check if the session is retrieving the cart
Console.WriteLine("Cart retrieved from session: " + JsonConvert.SerializeObject(cart));
return cart;
}

private void SaveShoppingCart(ShoppingCart shoppingCart)
{
var session = _httpContextAccessor.HttpContext?.Session;
if (session == null)
{
throw new InvalidOperationException("Session is not available.");
}

// Serialize and store the cart
session.SetObjectAsJson(CartSessionKey, shoppingCart);

// DEBUG: Retrieve the cart immediately after saving to confirm it was saved
var sessionCart = session.GetObjectFromJson(CartSessionKey);

// Log the cart to the console
Console.WriteLine("Cart in session after Save: "  + JsonConvert.SerializeObject(sessionCart));

if (sessionCart == null || sessionCart.Items.Count == 0)
{
Console.WriteLine("Error: Shopping cart was not saved properly.");
}
}
}
Views/ShoppingCart/Index.cshtml ->

Код: Выделить всё

@{
ViewData["Title"] = "Shopping Cart";
}

Your Shopping Cart




Title
Quantity
Price




@foreach (var item in ViewBag.Items)
{

@item.Book.Title
@item.Quantity
@(item.Book.Price * item.Quantity)

[[email protected](]Remove[/url]


}



[b]Total: [/b]@ViewBag.TotalPrice

[[email protected](]Clear Cart[/url]
[url=#]Checkout[/url]
BookService.cs ->

Код: Выделить всё

using System.Collections.Generic;
using System.Threading.Tasks;
using Bookshop_ASP.NET_Core_MVC_Application.Data;
using Bookshop_ASP.NET_Core_MVC_Application.Models;
using Microsoft.EntityFrameworkCore;

namespace Bookshop_ASP.NET_Core_MVC_Application.Services
{
public class BookService : IBookService
{
private readonly BookshopDbContext _context;

public BookService(BookshopDbContext context)
{
_context = context;
}

public async Task GetAllBooksAsync()
{
return await _context.Books
.Include(b => b.Author)
.Include(b => b.BookGenres)
.ThenInclude(bg => bg.Genre)
.ToListAsync();
}

public async Task GetBookByIdAsync(int id)
{

try
{
var book = await _context.Books
.Include(b => b.Author)
.Include(b => b.BookGenres)
.ThenInclude(bg => bg.Genre)
.FirstOrDefaultAsync(b => b.Id == id);

if (book == null)
{
Console.WriteLine($"No book found with ID: {id}");
}

return book;
}
catch (Exception ex)
{
// Log or throw the error to see if anything goes wrong during the query
Console.WriteLine($"Error fetching book: {ex.Message}");
return null;
}
}

public async Task CreateBookAsync(Book book)
{
_context.Add(book);
await _context.SaveChangesAsync();
}

public async Task UpdateBookAsync(Book book)
{
_context.Update(book);
await _context.SaveChangesAsync();
}

public async Task DeleteBookAsync(int id)
{
var book = await _context.Books.FindAsync(id);
if (book != null)
{
_context.Books.Remove(book);
await _context.SaveChangesAsync();
}
}

public async Task GetAuthorsAsync()
{
return await _context.Authors.ToListAsync();
}

public async Task  GetGenresAsync()
{
return await _context.Genres.ToListAsync();
}
}
}
BooksController.cs ->

Код: Выделить всё

using Bookshop_ASP.NET_Core_MVC_Application.Models;
using Bookshop_ASP.NET_Core_MVC_Application.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;

namespace Bookshop_ASP.NET_Core_MVC_Application.Controllers
{
public class BooksController : Controller
{
private readonly IBookService _bookService;

public BooksController(IBookService bookService)
{
_bookService = bookService;
}

// GET: BooksController
public async Task Index()
{
var books = await _bookService.GetAllBooksAsync();
return View(books);
}

// GET: BooksController/Details/5
public async Task Details(int id)
{
var book = await _bookService.GetBookByIdAsync(id);
if (book == null)
{
return NotFound();
}

return View(book);
}

[HttpGet]
public async Task Create()
{
ViewBag.Authors = await _bookService.GetAuthorsAsync();
ViewBag.Genres = await _bookService.GetGenresAsync();
return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task Create(Book book, int[] GenreIds)
{
Console.WriteLine("AuthorId: " + book.AuthorId);
Console.WriteLine("BookGenres: " + book.BookGenres);

// Manually find the author based on AuthorId and assign it
var author = (await _bookService.GetAuthorsAsync())
.FirstOrDefault(a => a.Id == book.AuthorId);
book.Author = author;

// Map selected genres to BookGenres collection
var selectedGenres = await _bookService.GetGenresAsync();
foreach (var genreId in GenreIds)
{
var genre = selectedGenres.FirstOrDefault(g => g.Id == genreId);
if (genre != null)
{
book.BookGenres.Add(new BookGenre { Book = book, Genre = genre });
}
}

if (!ModelState.IsValid)
{
foreach (var error in ModelState.Values.SelectMany(v => v.Errors))
{
Console.WriteLine(error.ErrorMessage);
}
}

if (ModelState.IsValid)
{
if (author != null)
{
await _bookService.CreateBookAsync(book);
return RedirectToAction(nameof(Index));
}
else
{
ModelState.AddModelError("AuthorId", "Invalid author selected.");
}
}

ViewBag.Authors = await _bookService.GetAuthorsAsync();
ViewBag.Genres = await _bookService.GetGenresAsync();
return View(book);
}

// GET: BooksController/Edit/5
public async Task Edit(int id)
{
var book = await _bookService.GetBookByIdAsync(id);
if (book == null) return NotFound();

ViewBag.Authors = await _bookService.GetAuthorsAsync();
ViewBag.Genres = await _bookService.GetGenresAsync();
return View(book);
}

// POST: BooksController/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task  Edit(int id, [Bind("Id, Title, Price, PublicationDate, Description, AuthorId, GenreId, ImageUrl")] Book book)
{
if (id != book.Id) return NotFound();

if (ModelState.IsValid)
{
await _bookService.UpdateBookAsync(book);
return RedirectToAction(nameof(Index));
}

ViewBag.Authors = await _bookService.GetAuthorsAsync();
ViewBag.Genres = await _bookService.GetGenresAsync();
return View(book);
}

// GET: BooksController/Delete/5
public async Task Delete(int? id)
{
if (id == null)
{
return NotFound();
}

var book = await _bookService.GetBookByIdAsync(id.Value);

if (book == null)
{
return NotFound();
}

return View(book);
}

// POST: BooksController/Delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task DeleteConfirmed(int id)
{
await _bookService.DeleteBookAsync(id);
return RedirectToAction(nameof(Index));
}
}
}
Это моя программа.cs ->

Код: Выделить всё

using Bookshop_ASP.NET_Core_MVC_Application.Data;
using Microsoft.EntityFrameworkCore;
using Bookshop_ASP.NET_Core_MVC_Application.Services;
using Bookshop.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddDbContext(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))
.EnableSensitiveDataLogging()
.LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information));

builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddHttpContextAccessor();
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30); // Adjust this as necessary
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});

builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

app.UseRouting();
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();

app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");

BookshopDbContextSeeder.Seed(app);

app.Run();
Когда я говорю, что теряю все, что имею в виду в методе ShoppingCartService.cs «public async Task AddToCart(int bookId)», программа успешно заполняет var ShoppingCart и var book и успешно выполняет ShoppingCart. Items.Add(new CartItem {BookId = bookId, Book = book, Quantity = 1 }); но как только он попадает в метод SaveShoppingCart(shoppingCart); внутри него первая строка кода -> var session = _httpContextAccessor.HttpContext?.Session; сеанс равен нулю... и с этого момента я теряю свою заполненную корзину с товарами и т. д. и т. п., а также иногда, хотя и не всегда, я получаю ошибку в методе BookService.cs -> public async Task GetBookByIdAsync (int id).
Я знаю, что использовал ChatGPT для генерации большей части кода и только что собрал его! Не распинай меня!

Подробнее здесь: https://stackoverflow.com/questions/790 ... my-project
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»