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.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
||||||
{
|
{
|
||||||
@@ -6,5 +7,21 @@ namespace Microsoft.eShopWeb.ApplicationCore.Entities
|
|||||||
{
|
{
|
||||||
public string BuyerId { get; set; }
|
public string BuyerId { get; set; }
|
||||||
public List<BasketItem> Items { get; set; } = new List<BasketItem>();
|
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 Microsoft.eShopWeb.ApplicationCore.Entities;
|
|
||||||
using System.Security.Principal;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace ApplicationCore.Interfaces
|
namespace ApplicationCore.Interfaces
|
||||||
{
|
{
|
||||||
public interface IBasketService
|
public interface IBasketService
|
||||||
{
|
{
|
||||||
Task<Basket> GetBasket(ApplicationUser user);
|
Task<Basket> GetBasket(string basketId);
|
||||||
}
|
Task<Basket> CreateBasket();
|
||||||
|
Task<Basket> CreateBasketForUser(string userId);
|
||||||
public interface IIdentityParser<T>
|
Task UpdateBasket(Basket basket);
|
||||||
{
|
|
||||||
T Parse(IPrincipal principal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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 System.Threading.Tasks;
|
||||||
using ApplicationCore.Interfaces;
|
using ApplicationCore.Interfaces;
|
||||||
using ApplicationCore.Entities;
|
|
||||||
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
using Microsoft.eShopWeb.ApplicationCore.Entities;
|
||||||
using System;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb.Controllers
|
namespace Microsoft.eShopWeb.Controllers
|
||||||
{
|
{
|
||||||
public class CartController : Controller
|
public class CartController : Controller
|
||||||
{
|
{
|
||||||
private readonly ICatalogService _catalogSvc;
|
private readonly IBasketService _basketService;
|
||||||
private readonly IBasketService _basketSvc;
|
//private readonly IIdentityParser<ApplicationUser> _appUserParser;
|
||||||
private readonly IIdentityParser<ApplicationUser> _appUserParser;
|
private const string _basketSessionKey = "basketId";
|
||||||
|
|
||||||
public CartController(IBasketService basketSvc,
|
public CartController(IBasketService basketService)
|
||||||
IIdentityParser<ApplicationUser> appUserParser)
|
// IIdentityParser<ApplicationUser> appUserParser)
|
||||||
{
|
{
|
||||||
//_catalogSvc = catalogSvc;
|
_basketService = basketService;
|
||||||
_basketSvc = basketSvc;
|
// _appUserParser = appUserParser;
|
||||||
_appUserParser = appUserParser;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GET: /<controller>/
|
// GET: /<controller>/
|
||||||
public async Task<IActionResult> Index()
|
public async Task<IActionResult> Index()
|
||||||
{
|
{
|
||||||
var user = _appUserParser.Parse(HttpContext.User);
|
//var user = _appUserParser.Parse(HttpContext.User);
|
||||||
var viewmodel = await _basketSvc.GetBasket(user);
|
var basket = await GetBasketFromSessionAsync();
|
||||||
|
|
||||||
return View(viewmodel);
|
return View(basket);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IActionResult> AddToCart(CatalogItem productDetails)
|
public async Task<IActionResult> AddToCart(CatalogItem productDetails)
|
||||||
{
|
{
|
||||||
if (productDetails.Id != null)
|
if (productDetails?.Id == null)
|
||||||
{
|
{
|
||||||
var user = _appUserParser.Parse(HttpContext.User);
|
return RedirectToAction("Index", "Catalog");
|
||||||
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");
|
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 CatalogContext(DbContextOptions<CatalogContext> options) : base(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
public DbSet<Basket> Baskets { get; set; }
|
||||||
public DbSet<CatalogItem> CatalogItems { get; set; }
|
public DbSet<CatalogItem> CatalogItems { get; set; }
|
||||||
public DbSet<CatalogBrand> CatalogBrands { get; set; }
|
public DbSet<CatalogBrand> CatalogBrands { get; set; }
|
||||||
public DbSet<CatalogType> CatalogTypes { 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 ApplicationCore.Interfaces;
|
||||||
using Infrastructure.FileSystem;
|
using Infrastructure.FileSystem;
|
||||||
using Infrastructure.Logging;
|
using Infrastructure.Logging;
|
||||||
|
using Web.Services;
|
||||||
|
|
||||||
namespace Microsoft.eShopWeb
|
namespace Microsoft.eShopWeb
|
||||||
{
|
{
|
||||||
@@ -41,8 +42,8 @@ namespace Microsoft.eShopWeb
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//c.UseInMemoryDatabase("Catalog");
|
c.UseInMemoryDatabase("Catalog");
|
||||||
c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection"));
|
//c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection"));
|
||||||
c.ConfigureWarnings(wb =>
|
c.ConfigureWarnings(wb =>
|
||||||
{
|
{
|
||||||
//By default, in this application, we don't want to have client evaluations
|
//By default, in this application, we don't want to have client evaluations
|
||||||
@@ -57,8 +58,8 @@ namespace Microsoft.eShopWeb
|
|||||||
|
|
||||||
// Add Identity DbContext
|
// Add Identity DbContext
|
||||||
services.AddDbContext<AppIdentityDbContext>(options =>
|
services.AddDbContext<AppIdentityDbContext>(options =>
|
||||||
//options.UseInMemoryDatabase("Identity"));
|
options.UseInMemoryDatabase("Identity"));
|
||||||
options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));
|
//options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));
|
||||||
|
|
||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
.AddEntityFrameworkStores<AppIdentityDbContext>()
|
.AddEntityFrameworkStores<AppIdentityDbContext>()
|
||||||
@@ -66,10 +67,19 @@ namespace Microsoft.eShopWeb
|
|||||||
|
|
||||||
services.AddMemoryCache();
|
services.AddMemoryCache();
|
||||||
services.AddScoped<ICatalogService, CachedCatalogService>();
|
services.AddScoped<ICatalogService, CachedCatalogService>();
|
||||||
|
services.AddScoped<IBasketService, BasketService>();
|
||||||
services.AddScoped<CatalogService>();
|
services.AddScoped<CatalogService>();
|
||||||
services.Configure<CatalogSettings>(Configuration);
|
services.Configure<CatalogSettings>(Configuration);
|
||||||
services.AddSingleton<IImageService, LocalFileImageService>();
|
services.AddSingleton<IImageService, LocalFileImageService>();
|
||||||
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
|
||||||
|
|
||||||
|
|
||||||
|
// Add memory cache services
|
||||||
|
services.AddMemoryCache();
|
||||||
|
|
||||||
|
// Add session related services.
|
||||||
|
services.AddSession();
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
|
||||||
_services = services;
|
_services = services;
|
||||||
@@ -110,6 +120,8 @@ namespace Microsoft.eShopWeb
|
|||||||
app.UseExceptionHandler("/Catalog/Error");
|
app.UseExceptionHandler("/Catalog/Error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseSession();
|
||||||
|
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
|
||||||
app.UseIdentity();
|
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">
|
<form asp-controller="Cart" asp-action="AddToCart">
|
||||||
|
|
||||||
<img class="esh-catalog-thumbnail" src="@Model.PictureUri" />
|
<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">
|
<div class="esh-catalog-name">
|
||||||
<span>@Model.Name</span>
|
<span>@Model.Name</span>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.1" />
|
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
|
<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.AspNetCore.StaticFiles" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="1.1.2" />
|
||||||
|
|||||||
Reference in New Issue
Block a user