Cleaning things up and getting add item to cart working for anonymous or authenticated users.
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace ApplicationCore.Entities
|
||||
{
|
||||
public class ApplicationUser : ClaimsIdentity
|
||||
{
|
||||
public string UserId { get; set; }
|
||||
public string UserName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
||||
{
|
||||
@@ -6,5 +7,21 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
||||
{
|
||||
public string BuyerId { get; set; }
|
||||
public List<BasketItem> Items { get; set; } = new List<BasketItem>();
|
||||
|
||||
public void AddItem(int productId, decimal unitPrice, int quantity = 1)
|
||||
{
|
||||
if(!Items.Any(i => i.ProductId == productId))
|
||||
{
|
||||
Items.Add(new BasketItem()
|
||||
{
|
||||
ProductId = productId,
|
||||
Quantity = quantity,
|
||||
UnitPrice = unitPrice
|
||||
});
|
||||
return;
|
||||
}
|
||||
var existingItem = Items.FirstOrDefault(i => i.ProductId == productId);
|
||||
existingItem.Quantity += quantity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
using ApplicationCore.Entities;
|
||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||
using System.Security.Principal;
|
||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ApplicationCore.Interfaces
|
||||
{
|
||||
public interface IBasketService
|
||||
{
|
||||
Task<Basket> GetBasket(ApplicationUser user);
|
||||
}
|
||||
|
||||
public interface IIdentityParser<T>
|
||||
{
|
||||
T Parse(IPrincipal principal);
|
||||
Task<Basket> GetBasket(string basketId);
|
||||
Task<Basket> CreateBasket();
|
||||
Task<Basket> CreateBasketForUser(string userId);
|
||||
Task UpdateBasket(Basket basket);
|
||||
}
|
||||
}
|
||||
|
||||
9
src/ApplicationCore/Interfaces/IIdentityParser.cs
Normal file
9
src/ApplicationCore/Interfaces/IIdentityParser.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace ApplicationCore.Interfaces
|
||||
{
|
||||
public interface IIdentityParser<T>
|
||||
{
|
||||
T Parse(IPrincipal principal);
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,4 @@ namespace Infrastructure.Identity
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationUser : IdentityUser
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
10
src/Infrastructure/Identity/ApplicationUser.cs
Normal file
10
src/Infrastructure/Identity/ApplicationUser.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
|
||||
namespace Infrastructure.Identity
|
||||
{
|
||||
public class ApplicationUser : IdentityUser
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,63 @@
|
||||
using Microsoft.eShopWeb.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Threading.Tasks;
|
||||
using ApplicationCore.Interfaces;
|
||||
using ApplicationCore.Entities;
|
||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.eShopWeb.Controllers
|
||||
{
|
||||
public class CartController : Controller
|
||||
{
|
||||
private readonly ICatalogService _catalogSvc;
|
||||
private readonly IBasketService _basketSvc;
|
||||
private readonly IIdentityParser<ApplicationUser> _appUserParser;
|
||||
private readonly IBasketService _basketService;
|
||||
//private readonly IIdentityParser<ApplicationUser> _appUserParser;
|
||||
private const string _basketSessionKey = "basketId";
|
||||
|
||||
public CartController(IBasketService basketSvc,
|
||||
IIdentityParser<ApplicationUser> appUserParser)
|
||||
public CartController(IBasketService basketService)
|
||||
// IIdentityParser<ApplicationUser> appUserParser)
|
||||
{
|
||||
//_catalogSvc = catalogSvc;
|
||||
_basketSvc = basketSvc;
|
||||
_appUserParser = appUserParser;
|
||||
_basketService = basketService;
|
||||
// _appUserParser = appUserParser;
|
||||
}
|
||||
|
||||
|
||||
// GET: /<controller>/
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
var viewmodel = await _basketSvc.GetBasket(user);
|
||||
//var user = _appUserParser.Parse(HttpContext.User);
|
||||
var basket = await GetBasketFromSessionAsync();
|
||||
|
||||
return View(viewmodel);
|
||||
return View(basket);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> AddToCart(CatalogItem productDetails)
|
||||
{
|
||||
if (productDetails.Id != null)
|
||||
if (productDetails?.Id == null)
|
||||
{
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
var product = new BasketItem()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
Quantity = 1,
|
||||
UnitPrice = productDetails.Price,
|
||||
ProductId = productDetails.Id
|
||||
};
|
||||
//await _basketSvc.AddItemToBasket(user, product);
|
||||
return RedirectToAction("Index", "Catalog");
|
||||
}
|
||||
return RedirectToAction("Index", "Catalog");
|
||||
var basket = await GetBasketFromSessionAsync();
|
||||
|
||||
basket.AddItem(productDetails.Id, productDetails.Price, 1);
|
||||
|
||||
await _basketService.UpdateBasket(basket);
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
private async Task<Basket> GetBasketFromSessionAsync()
|
||||
{
|
||||
string basketId = HttpContext.Session.GetString(_basketSessionKey);
|
||||
Basket basket = null;
|
||||
if (basketId == null)
|
||||
{
|
||||
basket = await _basketService.CreateBasketForUser(User.Identity.Name);
|
||||
HttpContext.Session.SetString(_basketSessionKey, basket.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
basket = await _basketService.GetBasket(basketId);
|
||||
}
|
||||
return basket;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Microsoft.eShopWeb.Infrastructure
|
||||
public CatalogContext(DbContextOptions<CatalogContext> options) : base(options)
|
||||
{
|
||||
}
|
||||
public DbSet<Basket> Baskets { get; set; }
|
||||
public DbSet<CatalogItem> CatalogItems { get; set; }
|
||||
public DbSet<CatalogBrand> CatalogBrands { get; set; }
|
||||
public DbSet<CatalogType> CatalogTypes { get; set; }
|
||||
|
||||
53
src/Web/Services/BasketService.cs
Normal file
53
src/Web/Services/BasketService.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using ApplicationCore.Interfaces;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||
using Microsoft.eShopWeb.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Web.Services
|
||||
{
|
||||
public class BasketService : IBasketService
|
||||
{
|
||||
private readonly CatalogContext _context;
|
||||
|
||||
public BasketService(CatalogContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
public async Task<Basket> GetBasket(string basketId)
|
||||
{
|
||||
var basket = await _context.Baskets
|
||||
.Include(b => b.Items)
|
||||
.FirstOrDefaultAsync(b => b.Id == basketId);
|
||||
if (basket == null)
|
||||
{
|
||||
basket = new Basket();
|
||||
_context.Baskets.Add(basket);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
return basket;
|
||||
}
|
||||
|
||||
public Task<Basket> CreateBasket()
|
||||
{
|
||||
return CreateBasketForUser(null);
|
||||
}
|
||||
|
||||
public async Task<Basket> CreateBasketForUser(string userId)
|
||||
{
|
||||
var basket = new Basket();
|
||||
_context.Baskets.Add(basket);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
return basket;
|
||||
}
|
||||
|
||||
|
||||
public async Task UpdateBasket(Basket basket)
|
||||
{
|
||||
// only need to save changes here
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Http;
|
||||
using ApplicationCore.Interfaces;
|
||||
using Infrastructure.FileSystem;
|
||||
using Infrastructure.Logging;
|
||||
using Web.Services;
|
||||
|
||||
namespace Microsoft.eShopWeb
|
||||
{
|
||||
@@ -41,8 +42,8 @@ namespace Microsoft.eShopWeb
|
||||
{
|
||||
try
|
||||
{
|
||||
//c.UseInMemoryDatabase("Catalog");
|
||||
c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection"));
|
||||
c.UseInMemoryDatabase("Catalog");
|
||||
//c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection"));
|
||||
c.ConfigureWarnings(wb =>
|
||||
{
|
||||
//By default, in this application, we don't want to have client evaluations
|
||||
@@ -57,8 +58,8 @@ namespace Microsoft.eShopWeb
|
||||
|
||||
// Add Identity DbContext
|
||||
services.AddDbContext<AppIdentityDbContext>(options =>
|
||||
//options.UseInMemoryDatabase("Identity"));
|
||||
options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));
|
||||
options.UseInMemoryDatabase("Identity"));
|
||||
//options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));
|
||||
|
||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
.AddEntityFrameworkStores<AppIdentityDbContext>()
|
||||
@@ -66,10 +67,19 @@ namespace Microsoft.eShopWeb
|
||||
|
||||
services.AddMemoryCache();
|
||||
services.AddScoped<ICatalogService, CachedCatalogService>();
|
||||
services.AddScoped<IBasketService, BasketService>();
|
||||
services.AddScoped<CatalogService>();
|
||||
services.Configure<CatalogSettings>(Configuration);
|
||||
services.AddSingleton<IImageService, LocalFileImageService>();
|
||||
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
||||
|
||||
|
||||
// Add memory cache services
|
||||
services.AddMemoryCache();
|
||||
|
||||
// Add session related services.
|
||||
services.AddSession();
|
||||
|
||||
services.AddMvc();
|
||||
|
||||
_services = services;
|
||||
@@ -110,6 +120,8 @@ namespace Microsoft.eShopWeb
|
||||
app.UseExceptionHandler("/Catalog/Error");
|
||||
}
|
||||
|
||||
app.UseSession();
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseIdentity();
|
||||
|
||||
32
src/Web/Views/Cart/Index.cshtml
Normal file
32
src/Web/Views/Cart/Index.cshtml
Normal file
@@ -0,0 +1,32 @@
|
||||
@using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||
@{
|
||||
ViewData["Title"] = "Catalog";
|
||||
@model Basket
|
||||
}
|
||||
<section class="esh-catalog-hero">
|
||||
<div class="container">
|
||||
<img class="esh-catalog-title" src="../images/main_banner_text.png" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="container">
|
||||
|
||||
@if (Model.Items.Any())
|
||||
{
|
||||
<div class="esh-catalog-items row">
|
||||
@foreach (var item in Model.Items)
|
||||
{
|
||||
<div class="esh-catalog-item col-md-4">
|
||||
@item.ProductId
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="esh-catalog-items row">
|
||||
Cart is empty.
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -4,7 +4,7 @@
|
||||
<form asp-controller="Cart" asp-action="AddToCart">
|
||||
|
||||
<img class="esh-catalog-thumbnail" src="@Model.PictureUri" />
|
||||
<input class="esh-catalog-button @((!User.Identity.IsAuthenticated) ? "is-disabled" : "")" type="submit" value="[ ADD TO CART ]" />
|
||||
<input class="esh-catalog-button" type="submit" value="[ ADD TO CART ]" />
|
||||
|
||||
<div class="esh-catalog-name">
|
||||
<span>@Model.Name</span>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Session" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.2" />
|
||||
|
||||
Reference in New Issue
Block a user