Exercise Files
This commit is contained in:
108
Ch07/07_03_Begin/Website/Features/Cart/Cart.cshtml
Normal file
108
Ch07/07_03_Begin/Website/Features/Cart/Cart.cshtml
Normal file
@ -0,0 +1,108 @@
|
||||
@model HPlusSports.Models.ShoppingCart
|
||||
|
||||
@{
|
||||
ViewBag.Title = "My Cart";
|
||||
}
|
||||
|
||||
@if (TempData.SuccessMessage() != null)
|
||||
{
|
||||
<div class="alert alert-success alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
@TempData.SuccessMessage()
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="cart row">
|
||||
|
||||
<div>
|
||||
<hr />
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="col-md-1">
|
||||
</th>
|
||||
<th class="col-md-6">
|
||||
Product
|
||||
</th>
|
||||
<th class="col-md-1">
|
||||
Quantity
|
||||
</th>
|
||||
<th class="col-md-2">
|
||||
Price
|
||||
</th>
|
||||
<th class="col-md-2">
|
||||
Subtotal
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.Items)
|
||||
{
|
||||
<tr class="text-middle">
|
||||
<td>
|
||||
<a href="@Url.Action("Remove", "Cart", new { id = item.Id })">
|
||||
<i class="glyphicon glyphicon-remove text-danger"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="@Url.Product(item.SKU)">
|
||||
<img class="product-image img-thumbnail" src="@Url.Action("Product", "Images", new { id = item.SKU })" />
|
||||
<span>@item.Name</span>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="@Url.Action("Add", "Cart", new { item.SKU, quantity = -1 })">
|
||||
<i class="glyphicon glyphicon-minus"></i>
|
||||
</a>
|
||||
@item.Quantity
|
||||
<a href="@Url.Action("Add", "Cart", new { item.SKU })">
|
||||
<i class="glyphicon glyphicon-plus"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
@item.Price.ToString("C")
|
||||
</td>
|
||||
<td>
|
||||
@item.Total.ToString("C")
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="text-primary">
|
||||
<td colspan="4" class="text-right">
|
||||
Subtotal
|
||||
</td>
|
||||
<td>
|
||||
@Model.Subtotal.ToString("C")
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="text-muted">
|
||||
<td colspan="4" class="text-right">
|
||||
Tax
|
||||
</td>
|
||||
<td>
|
||||
@Model.Tax.ToString("C")
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="text-muted">
|
||||
<td colspan="4" class="text-right">
|
||||
Shipping
|
||||
</td>
|
||||
<td>
|
||||
@Model.Shipping.ToString("C")
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="text-primary text-large">
|
||||
<th colspan="4" class="text-right">
|
||||
Total
|
||||
</th>
|
||||
<th>
|
||||
@Model.Total.ToString("C")
|
||||
</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
132
Ch07/07_03_Begin/Website/Features/Cart/CartController.cs
Normal file
132
Ch07/07_03_Begin/Website/Features/Cart/CartController.cs
Normal file
@ -0,0 +1,132 @@
|
||||
using HPlusSports.Models;
|
||||
using System;
|
||||
using System.Data.Entity.Validation;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace HPlusSports.Controllers
|
||||
{
|
||||
public class CartController : Controller
|
||||
{
|
||||
private readonly HPlusSportsDbContext _context;
|
||||
|
||||
public CartController()
|
||||
: this(new HPlusSportsDbContext())
|
||||
{
|
||||
}
|
||||
|
||||
public CartController(HPlusSportsDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
{
|
||||
var cart = GetCart();
|
||||
|
||||
if (cart.Items.Any())
|
||||
return View("Cart", cart);
|
||||
|
||||
return View("EmptyCart");
|
||||
}
|
||||
|
||||
public ActionResult Add(string sku, int quantity = 1)
|
||||
{
|
||||
var product = _context.Products.FirstOrDefault(x => x.SKU == sku);
|
||||
|
||||
var cart = GetCart();
|
||||
|
||||
var item = cart.Items.FirstOrDefault(x => x.SKU == sku);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
item = new ShoppingCartItem
|
||||
{
|
||||
SKU = product?.SKU,
|
||||
Name = product?.Name,
|
||||
MSRP = (product?.MSRP).GetValueOrDefault(),
|
||||
Price = (product?.Price).GetValueOrDefault(),
|
||||
Quantity = quantity,
|
||||
};
|
||||
|
||||
cart.Items.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Quantity += quantity;
|
||||
}
|
||||
|
||||
if (item.Quantity <= 0)
|
||||
{
|
||||
cart.Items.Remove(item);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_context.SaveChanges();
|
||||
}
|
||||
catch (DbEntityValidationException ex)
|
||||
{
|
||||
var errors = ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors);
|
||||
|
||||
foreach (var error in errors)
|
||||
{
|
||||
ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
TempData.SuccessMessage($"Successfully added {item.Name} to the cart");
|
||||
|
||||
return RedirectToAction("Index", "Cart");
|
||||
}
|
||||
|
||||
public ActionResult Remove(long id)
|
||||
{
|
||||
var cart = GetCart();
|
||||
|
||||
var item = cart.Items.FirstOrDefault(x => x.Id == id);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
ModelState.AddModelError("", "Missing or invalid cart item");
|
||||
return View();
|
||||
}
|
||||
|
||||
cart.Items.Remove(item);
|
||||
|
||||
_context.SaveChanges();
|
||||
|
||||
return RedirectToAction("Index", "Cart");
|
||||
}
|
||||
|
||||
private ShoppingCart GetCart()
|
||||
{
|
||||
var userId = GetUserId(this);
|
||||
|
||||
var cart =
|
||||
_context.ShoppingCarts
|
||||
.Include("Items")
|
||||
.FirstOrDefault(x => x.UserId == userId);
|
||||
|
||||
if (cart == null)
|
||||
{
|
||||
cart = new ShoppingCart { UserId = userId };
|
||||
_context.ShoppingCarts.Add(cart);
|
||||
_context.SaveChanges();
|
||||
}
|
||||
|
||||
cart.Recalculate();
|
||||
|
||||
return cart;
|
||||
}
|
||||
|
||||
// Overwriteable function for unit testing
|
||||
internal Func<Controller, string> GetUserId =
|
||||
(controller) => controller.User.Identity.Name;
|
||||
}
|
||||
}
|
||||
16
Ch07/07_03_Begin/Website/Features/Cart/EmptyCart.cshtml
Normal file
16
Ch07/07_03_Begin/Website/Features/Cart/EmptyCart.cshtml
Normal file
@ -0,0 +1,16 @@
|
||||
@model HPlusSports.Models.ShoppingCart
|
||||
|
||||
@{
|
||||
ViewBag.Title = "Cart";
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="well well-lg">
|
||||
<p>Your shopping cart is empty!</p>
|
||||
<p>
|
||||
Head on over to
|
||||
@Html.ActionLink("the Product Catalog", "Index", "Products")
|
||||
to find something!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user