Merge pull request #1 from aspnet/ControllerUpdates
Everything but the kitchen async... (Updates to how Music Store controllers use data)
Specifically:
- Dispose contexts
- Use async wherever possible
- Stop using initializers (currently hard-coded to drop and recreate each run)
- Some general cleanup
- Stop using AttachDbFilename
Not included here:
- No major changes to app structure
- No major changes to data model
- No major changes to error handling, concurrency, etc.
This commit is contained in:
commit
b8f5824114
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<packages>
|
|
||||||
<package id="Sake" version="0.2" />
|
|
||||||
</packages>
|
|
||||||
|
|
@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MusicStore.k10", "src\Music
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MusicStore.net45", "src\MusicStore\MusicStore.net45.csproj", "{9C8A2D1F-D430-46DF-8F00-39E378EC8FB2}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MusicStore.net45", "src\MusicStore\MusicStore.net45.csproj", "{9C8A2D1F-D430-46DF-8F00-39E378EC8FB2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{44621553-AA7D-4893-8834-79582A7D8348}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,54 @@
|
||||||
using Microsoft.AspNet.Identity;
|
using System.Configuration;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Identity;
|
||||||
using Microsoft.AspNet.Identity.EntityFramework;
|
using Microsoft.AspNet.Identity.EntityFramework;
|
||||||
using Microsoft.Owin;
|
|
||||||
using Microsoft.Owin.Security.Cookies;
|
|
||||||
using MvcMusicStore.Models;
|
using MvcMusicStore.Models;
|
||||||
using Owin;
|
using Owin;
|
||||||
using System.Configuration;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MvcMusicStore
|
namespace MvcMusicStore
|
||||||
{
|
{
|
||||||
public partial class Startup
|
public partial class Startup
|
||||||
{
|
{
|
||||||
|
private const string RoleName = "Administrator";
|
||||||
|
|
||||||
public void ConfigureApp(IAppBuilder app)
|
public void ConfigureApp(IAppBuilder app)
|
||||||
{
|
{
|
||||||
System.Data.Entity.Database.SetInitializer(new MvcMusicStore.Models.SampleData());
|
using (var context = new MusicStoreEntities())
|
||||||
|
|
||||||
CreateAdminUser();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void CreateAdminUser()
|
|
||||||
{
|
|
||||||
string _username = ConfigurationManager.AppSettings["DefaultAdminUsername"];
|
|
||||||
string _password = ConfigurationManager.AppSettings["DefaultAdminPassword"];
|
|
||||||
string _role = "Administrator";
|
|
||||||
|
|
||||||
var context = new ApplicationDbContext();
|
|
||||||
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
|
|
||||||
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
|
|
||||||
|
|
||||||
var role = new IdentityRole(_role);
|
|
||||||
var result = await roleManager.RoleExistsAsync(_role);
|
|
||||||
if (result == false)
|
|
||||||
{
|
{
|
||||||
await roleManager.CreateAsync(role);
|
context.Database.Delete();
|
||||||
|
context.Database.Create();
|
||||||
|
|
||||||
|
new SampleData().Seed(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = await userManager.FindByNameAsync(_username);
|
CreateAdminUser().Wait();
|
||||||
if (user == null)
|
}
|
||||||
|
|
||||||
|
private async Task CreateAdminUser()
|
||||||
|
{
|
||||||
|
var username = ConfigurationManager.AppSettings["DefaultAdminUsername"];
|
||||||
|
var password = ConfigurationManager.AppSettings["DefaultAdminPassword"];
|
||||||
|
|
||||||
|
using (var context = new ApplicationDbContext())
|
||||||
{
|
{
|
||||||
user = new ApplicationUser { UserName = _username };
|
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
|
||||||
await userManager.CreateAsync(user, _password);
|
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
|
||||||
await userManager.AddToRoleAsync(user.Id, _role);
|
|
||||||
|
var role = new IdentityRole(RoleName);
|
||||||
|
|
||||||
|
var result = await roleManager.RoleExistsAsync(RoleName);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
await roleManager.CreateAsync(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await userManager.FindByNameAsync(username);
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = new ApplicationUser { UserName = username };
|
||||||
|
await userManager.CreateAsync(user, password);
|
||||||
|
await userManager.AddToRoleAsync(user.Id, RoleName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using Microsoft.AspNet.Identity;
|
using Microsoft.AspNet.Identity;
|
||||||
using Microsoft.AspNet.Identity.EntityFramework;
|
using Microsoft.AspNet.Identity.EntityFramework;
|
||||||
|
using Microsoft.AspNet.Identity.Owin;
|
||||||
using Microsoft.Owin.Security;
|
using Microsoft.Owin.Security;
|
||||||
using MvcMusicStore.Models;
|
using MvcMusicStore.Models;
|
||||||
|
|
||||||
|
|
@ -15,6 +14,18 @@ namespace MvcMusicStore.Controllers
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class AccountController : Controller
|
public class AccountController : Controller
|
||||||
{
|
{
|
||||||
|
public enum ManageMessageId
|
||||||
|
{
|
||||||
|
ChangePasswordSuccess,
|
||||||
|
SetPasswordSuccess,
|
||||||
|
RemoveLoginSuccess,
|
||||||
|
Error
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string XsrfKey = "XsrfId";
|
||||||
|
|
||||||
|
private UserManager<ApplicationUser> _userManager;
|
||||||
|
|
||||||
public AccountController()
|
public AccountController()
|
||||||
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
|
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
|
||||||
{
|
{
|
||||||
|
|
@ -22,33 +33,35 @@ namespace MvcMusicStore.Controllers
|
||||||
|
|
||||||
public AccountController(UserManager<ApplicationUser> userManager)
|
public AccountController(UserManager<ApplicationUser> userManager)
|
||||||
{
|
{
|
||||||
UserManager = userManager;
|
_userManager = userManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserManager<ApplicationUser> UserManager { get; private set; }
|
private IAuthenticationManager AuthenticationManager
|
||||||
|
|
||||||
private void MigrateShoppingCart(string UserName)
|
|
||||||
{
|
{
|
||||||
var storeDb = new MusicStoreEntities();
|
get { return HttpContext.GetOwinContext().Authentication; }
|
||||||
|
}
|
||||||
// Associate shopping cart items with logged-in user
|
|
||||||
var cart = ShoppingCart.GetCart(storeDb, this.HttpContext);
|
private async Task MigrateShoppingCart(string userName)
|
||||||
cart.MigrateCart(UserName);
|
{
|
||||||
storeDb.SaveChanges();
|
using (var storeContext = new MusicStoreEntities())
|
||||||
|
{
|
||||||
Session[ShoppingCart.CartSessionKey] = UserName;
|
var cart = ShoppingCart.GetCart(storeContext, this);
|
||||||
|
|
||||||
|
await cart.MigrateCart(userName);
|
||||||
|
|
||||||
|
Session[ShoppingCart.CartSessionKey] = userName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Account/Login
|
// GET: /Account/Login
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public ActionResult Login(string returnUrl)
|
public ActionResult Login(string returnUrl)
|
||||||
{
|
{
|
||||||
ViewBag.ReturnUrl = returnUrl;
|
ViewBag.ReturnUrl = returnUrl;
|
||||||
|
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Account/Login
|
// POST: /Account/Login
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
|
|
@ -57,23 +70,20 @@ namespace MvcMusicStore.Controllers
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var user = await UserManager.FindAsync(model.UserName, model.Password);
|
var user = await _userManager.FindAsync(model.UserName, model.Password);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
await SignInAsync(user, model.RememberMe);
|
await SignInAsync(user, model.RememberMe);
|
||||||
|
|
||||||
return RedirectToLocal(returnUrl);
|
return RedirectToLocal(returnUrl);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
ModelState.AddModelError("", "Invalid username or password.");
|
||||||
ModelState.AddModelError("", "Invalid username or password.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got this far, something failed, redisplay form
|
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Account/Register
|
// GET: /Account/Register
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public ActionResult Register()
|
public ActionResult Register()
|
||||||
|
|
@ -81,7 +91,6 @@ namespace MvcMusicStore.Controllers
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Account/Register
|
// POST: /Account/Register
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
|
|
@ -90,85 +99,92 @@ namespace MvcMusicStore.Controllers
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
var user = new ApplicationUser() { UserName = model.UserName };
|
var user = new ApplicationUser { UserName = model.UserName };
|
||||||
var result = await UserManager.CreateAsync(user, model.Password);
|
var result = await _userManager.CreateAsync(user, model.Password);
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
await SignInAsync(user, isPersistent: false);
|
await SignInAsync(user, false);
|
||||||
|
|
||||||
return RedirectToAction("Index", "Home");
|
return RedirectToAction("Index", "Home");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
AddErrors(result);
|
||||||
AddErrors(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got this far, something failed, redisplay form
|
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Account/Disassociate
|
// POST: /Account/Disassociate
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
|
public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
|
||||||
{
|
{
|
||||||
ManageMessageId? message = null;
|
var result = await _userManager.RemoveLoginAsync(
|
||||||
IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
|
User.Identity.GetUserId(),
|
||||||
if (result.Succeeded)
|
new UserLoginInfo(loginProvider, providerKey));
|
||||||
{
|
|
||||||
message = ManageMessageId.RemoveLoginSuccess;
|
return RedirectToAction(
|
||||||
}
|
"Manage",
|
||||||
else
|
new { Message = result.Succeeded ? ManageMessageId.RemoveLoginSuccess : ManageMessageId.Error });
|
||||||
{
|
|
||||||
message = ManageMessageId.Error;
|
|
||||||
}
|
|
||||||
return RedirectToAction("Manage", new { Message = message });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Account/Manage
|
// GET: /Account/Manage
|
||||||
public ActionResult Manage(ManageMessageId? message)
|
public async Task<ActionResult> Manage(ManageMessageId? message)
|
||||||
{
|
{
|
||||||
ViewBag.StatusMessage =
|
switch (message)
|
||||||
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
|
{
|
||||||
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
|
case ManageMessageId.ChangePasswordSuccess:
|
||||||
: message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
|
ViewBag.StatusMessage = "Your password has been changed.";
|
||||||
: message == ManageMessageId.Error ? "An error has occurred."
|
break;
|
||||||
: "";
|
case ManageMessageId.SetPasswordSuccess:
|
||||||
ViewBag.HasLocalPassword = HasPassword();
|
ViewBag.StatusMessage = "Your password has been set.";
|
||||||
|
break;
|
||||||
|
case ManageMessageId.RemoveLoginSuccess:
|
||||||
|
ViewBag.StatusMessage = "The external login was removed.";
|
||||||
|
break;
|
||||||
|
case ManageMessageId.Error:
|
||||||
|
ViewBag.StatusMessage = "An error has occurred.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ViewBag.StatusMessage = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewBag.HasLocalPassword = await HasPasswordAsync();
|
||||||
ViewBag.ReturnUrl = Url.Action("Manage");
|
ViewBag.ReturnUrl = Url.Action("Manage");
|
||||||
|
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Account/Manage
|
// POST: /Account/Manage
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task<ActionResult> Manage(ManageUserViewModel model)
|
public async Task<ActionResult> Manage(ManageUserViewModel model)
|
||||||
{
|
{
|
||||||
bool hasPassword = HasPassword();
|
bool hasPassword = await HasPasswordAsync();
|
||||||
ViewBag.HasLocalPassword = hasPassword;
|
ViewBag.HasLocalPassword = hasPassword;
|
||||||
ViewBag.ReturnUrl = Url.Action("Manage");
|
ViewBag.ReturnUrl = Url.Action("Manage");
|
||||||
|
|
||||||
if (hasPassword)
|
if (hasPassword)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
|
var result = await _userManager.ChangePasswordAsync(
|
||||||
|
User.Identity.GetUserId(),
|
||||||
|
model.OldPassword,
|
||||||
|
model.NewPassword);
|
||||||
|
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
|
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
AddErrors(result);
|
||||||
AddErrors(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// User does not have a password so remove any validation errors caused by a missing OldPassword field
|
var state = ModelState["OldPassword"];
|
||||||
ModelState state = ModelState["OldPassword"];
|
|
||||||
if (state != null)
|
if (state != null)
|
||||||
{
|
{
|
||||||
state.Errors.Clear();
|
state.Errors.Clear();
|
||||||
|
|
@ -176,34 +192,32 @@ namespace MvcMusicStore.Controllers
|
||||||
|
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);
|
var result = await _userManager.AddPasswordAsync(
|
||||||
|
User.Identity.GetUserId(),
|
||||||
|
model.NewPassword);
|
||||||
|
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
|
return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
AddErrors(result);
|
||||||
AddErrors(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got this far, something failed, redisplay form
|
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Account/ExternalLogin
|
// POST: /Account/ExternalLogin
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public ActionResult ExternalLogin(string provider, string returnUrl)
|
public ActionResult ExternalLogin(string provider, string returnUrl)
|
||||||
{
|
{
|
||||||
// Request a redirect to the external login provider
|
return new ChallengeResult(provider,
|
||||||
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
|
Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Account/ExternalLoginCallback
|
// GET: /Account/ExternalLoginCallback
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
|
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
|
||||||
|
|
@ -214,55 +228,56 @@ namespace MvcMusicStore.Controllers
|
||||||
return RedirectToAction("Login");
|
return RedirectToAction("Login");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign in the user with this external login provider if the user already has a login
|
var user = await _userManager.FindAsync(loginInfo.Login);
|
||||||
var user = await UserManager.FindAsync(loginInfo.Login);
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
await SignInAsync(user, isPersistent: false);
|
await SignInAsync(user, false);
|
||||||
|
|
||||||
return RedirectToLocal(returnUrl);
|
return RedirectToLocal(returnUrl);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
ViewBag.ReturnUrl = returnUrl;
|
||||||
// If the user does not have an account, then prompt the user to create an account
|
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
|
||||||
ViewBag.ReturnUrl = returnUrl;
|
|
||||||
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
|
return View("ExternalLoginConfirmation",
|
||||||
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
|
new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Account/LinkLogin
|
// POST: /Account/LinkLogin
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public ActionResult LinkLogin(string provider)
|
public ActionResult LinkLogin(string provider)
|
||||||
{
|
{
|
||||||
// Request a redirect to the external login provider to link a login for the current user
|
|
||||||
return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
|
return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account"), User.Identity.GetUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Account/LinkLoginCallback
|
// GET: /Account/LinkLoginCallback
|
||||||
public async Task<ActionResult> LinkLoginCallback()
|
public async Task<ActionResult> LinkLoginCallback()
|
||||||
{
|
{
|
||||||
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
|
var loginInfo =
|
||||||
|
await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId());
|
||||||
|
|
||||||
if (loginInfo == null)
|
if (loginInfo == null)
|
||||||
{
|
{
|
||||||
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
|
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
|
||||||
}
|
}
|
||||||
var result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
|
|
||||||
|
var result = await _userManager.AddLoginAsync(User.Identity.GetUserId(), loginInfo.Login);
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
return RedirectToAction("Manage");
|
return RedirectToAction("Manage");
|
||||||
}
|
}
|
||||||
|
|
||||||
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
|
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Account/ExternalLoginConfirmation
|
// POST: /Account/ExternalLoginConfirmation
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
|
public async Task<ActionResult> ExternalLoginConfirmation(
|
||||||
|
ExternalLoginConfirmationViewModel model,
|
||||||
|
string returnUrl)
|
||||||
{
|
{
|
||||||
if (User.Identity.IsAuthenticated)
|
if (User.Identity.IsAuthenticated)
|
||||||
{
|
{
|
||||||
|
|
@ -277,35 +292,39 @@ namespace MvcMusicStore.Controllers
|
||||||
{
|
{
|
||||||
return View("ExternalLoginFailure");
|
return View("ExternalLoginFailure");
|
||||||
}
|
}
|
||||||
var user = new ApplicationUser() { UserName = model.UserName };
|
|
||||||
var result = await UserManager.CreateAsync(user);
|
var user = new ApplicationUser { UserName = model.UserName };
|
||||||
|
|
||||||
|
var result = await _userManager.CreateAsync(user);
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
result = await UserManager.AddLoginAsync(user.Id, info.Login);
|
result = await _userManager.AddLoginAsync(user.Id, info.Login);
|
||||||
|
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
{
|
{
|
||||||
await SignInAsync(user, isPersistent: false);
|
await SignInAsync(user, false);
|
||||||
return RedirectToLocal(returnUrl);
|
return RedirectToLocal(returnUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddErrors(result);
|
AddErrors(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewBag.ReturnUrl = returnUrl;
|
ViewBag.ReturnUrl = returnUrl;
|
||||||
|
|
||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Account/LogOff
|
// POST: /Account/LogOff
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[ValidateAntiForgeryToken]
|
[ValidateAntiForgeryToken]
|
||||||
public ActionResult LogOff()
|
public ActionResult LogOff()
|
||||||
{
|
{
|
||||||
AuthenticationManager.SignOut();
|
AuthenticationManager.SignOut();
|
||||||
|
|
||||||
return RedirectToAction("Index", "Home");
|
return RedirectToAction("Index", "Home");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Account/ExternalLoginFailure
|
// GET: /Account/ExternalLoginFailure
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public ActionResult ExternalLoginFailure()
|
public ActionResult ExternalLoginFailure()
|
||||||
|
|
@ -316,41 +335,34 @@ namespace MvcMusicStore.Controllers
|
||||||
[ChildActionOnly]
|
[ChildActionOnly]
|
||||||
public ActionResult RemoveAccountList()
|
public ActionResult RemoveAccountList()
|
||||||
{
|
{
|
||||||
var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId());
|
var linkedAccounts = _userManager.GetLogins(User.Identity.GetUserId());
|
||||||
|
|
||||||
ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
|
ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
|
||||||
return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
|
|
||||||
|
return PartialView("_RemoveAccountPartial", linkedAccounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing && UserManager != null)
|
if (disposing && _userManager != null)
|
||||||
{
|
{
|
||||||
UserManager.Dispose();
|
_userManager.Dispose();
|
||||||
UserManager = null;
|
_userManager = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Helpers
|
|
||||||
// Used for XSRF protection when adding external logins
|
|
||||||
private const string XsrfKey = "XsrfId";
|
|
||||||
|
|
||||||
private IAuthenticationManager AuthenticationManager
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return HttpContext.GetOwinContext().Authentication;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
|
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
|
||||||
{
|
{
|
||||||
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
|
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
|
||||||
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
|
|
||||||
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
|
|
||||||
|
|
||||||
// Migrate the user's shopping cart
|
var identity =
|
||||||
MigrateShoppingCart(user.UserName);
|
await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
|
||||||
|
|
||||||
|
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, identity);
|
||||||
|
|
||||||
|
await MigrateShoppingCart(user.UserName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddErrors(IdentityResult result)
|
private void AddErrors(IdentityResult result)
|
||||||
|
|
@ -363,61 +375,47 @@ namespace MvcMusicStore.Controllers
|
||||||
|
|
||||||
private bool HasPassword()
|
private bool HasPassword()
|
||||||
{
|
{
|
||||||
var user = UserManager.FindById(User.Identity.GetUserId());
|
var user = _userManager.FindById(User.Identity.GetUserId());
|
||||||
if (user != null)
|
|
||||||
{
|
return user != null && user.PasswordHash != null;
|
||||||
return user.PasswordHash != null;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ManageMessageId
|
private async Task<bool> HasPasswordAsync()
|
||||||
{
|
{
|
||||||
ChangePasswordSuccess,
|
var user = await _userManager.FindByIdAsync(User.Identity.GetUserId());
|
||||||
SetPasswordSuccess,
|
|
||||||
RemoveLoginSuccess,
|
return user != null && user.PasswordHash != null;
|
||||||
Error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionResult RedirectToLocal(string returnUrl)
|
private ActionResult RedirectToLocal(string returnUrl)
|
||||||
{
|
{
|
||||||
if (Url.IsLocalUrl(returnUrl))
|
return Url.IsLocalUrl(returnUrl)
|
||||||
{
|
? (ActionResult)Redirect(returnUrl)
|
||||||
return Redirect(returnUrl);
|
: RedirectToAction("Index", "Home");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return RedirectToAction("Index", "Home");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ChallengeResult : HttpUnauthorizedResult
|
private class ChallengeResult : HttpUnauthorizedResult
|
||||||
{
|
{
|
||||||
public ChallengeResult(string provider, string redirectUri) : this(provider, redirectUri, null)
|
private readonly string _loginProvider;
|
||||||
{
|
private readonly string _redirectUri;
|
||||||
}
|
private readonly string _userId;
|
||||||
|
|
||||||
public ChallengeResult(string provider, string redirectUri, string userId)
|
public ChallengeResult(string provider, string redirectUri, string userId = null)
|
||||||
{
|
{
|
||||||
LoginProvider = provider;
|
_loginProvider = provider;
|
||||||
RedirectUri = redirectUri;
|
_redirectUri = redirectUri;
|
||||||
UserId = userId;
|
_userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string LoginProvider { get; set; }
|
|
||||||
public string RedirectUri { get; set; }
|
|
||||||
public string UserId { get; set; }
|
|
||||||
|
|
||||||
public override void ExecuteResult(ControllerContext context)
|
public override void ExecuteResult(ControllerContext context)
|
||||||
{
|
{
|
||||||
var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
|
var properties = new AuthenticationProperties { RedirectUri = _redirectUri };
|
||||||
if (UserId != null)
|
if (_userId != null)
|
||||||
{
|
{
|
||||||
properties.Dictionary[XsrfKey] = UserId;
|
properties.Dictionary[XsrfKey] = _userId;
|
||||||
}
|
}
|
||||||
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
|
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, _loginProvider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Data.Entity;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using MvcMusicStore.Models;
|
using MvcMusicStore.Models;
|
||||||
|
|
||||||
|
|
@ -8,78 +9,56 @@ namespace MvcMusicStore.Controllers
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class CheckoutController : Controller
|
public class CheckoutController : Controller
|
||||||
{
|
{
|
||||||
MusicStoreEntities storeDB = new MusicStoreEntities();
|
private const string PromoCode = "FREE";
|
||||||
const string PromoCode = "FREE";
|
|
||||||
|
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Checkout/
|
// GET: /Checkout/
|
||||||
|
|
||||||
public ActionResult AddressAndPayment()
|
public ActionResult AddressAndPayment()
|
||||||
{
|
{
|
||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /Checkout/AddressAndPayment
|
// POST: /Checkout/AddressAndPayment
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public ActionResult AddressAndPayment(FormCollection values)
|
public async Task<ActionResult> AddressAndPayment(FormCollection values)
|
||||||
{
|
{
|
||||||
var order = new Order();
|
var order = new Order();
|
||||||
TryUpdateModel(order);
|
TryUpdateModel(order);
|
||||||
|
|
||||||
try
|
if (ModelState.IsValid
|
||||||
|
&& string.Equals(values["PromoCode"], PromoCode, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (string.Equals(values["PromoCode"], PromoCode,
|
order.Username = User.Identity.Name;
|
||||||
StringComparison.OrdinalIgnoreCase) == false)
|
order.OrderDate = DateTime.Now;
|
||||||
{
|
|
||||||
return View(order);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
order.Username = User.Identity.Name;
|
|
||||||
order.OrderDate = DateTime.Now;
|
|
||||||
|
|
||||||
//Add the Order
|
_storeContext.Orders.Add(order);
|
||||||
storeDB.Orders.Add(order);
|
|
||||||
|
|
||||||
//Process the order
|
await ShoppingCart.GetCart(_storeContext, this).CreateOrder(order);
|
||||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
|
||||||
cart.CreateOrder(order);
|
|
||||||
|
|
||||||
// Save all changes
|
await _storeContext.SaveChangesAsync();
|
||||||
storeDB.SaveChanges();
|
|
||||||
|
|
||||||
return RedirectToAction("Complete",
|
|
||||||
new { id = order.OrderId });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return RedirectToAction("Complete", new { id = order.OrderId });
|
||||||
}
|
}
|
||||||
catch
|
|
||||||
{
|
return View(order);
|
||||||
//Invalid - redisplay with errors
|
|
||||||
return View(order);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Checkout/Complete
|
// GET: /Checkout/Complete
|
||||||
|
public async Task<ActionResult> Complete(int id)
|
||||||
public ActionResult Complete(int id)
|
|
||||||
{
|
{
|
||||||
// Validate customer owns this order
|
return await _storeContext.Orders.AnyAsync(o => o.OrderId == id && o.Username == User.Identity.Name)
|
||||||
bool isValid = storeDB.Orders.Any(
|
? View(id)
|
||||||
o => o.OrderId == id &&
|
: View("Error");
|
||||||
o.Username == User.Identity.Name);
|
}
|
||||||
|
|
||||||
if (isValid)
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
{
|
{
|
||||||
return View(id);
|
_storeContext.Dispose();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return View("Error");
|
|
||||||
}
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Data.Entity;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web;
|
using System.Threading.Tasks;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using MvcMusicStore.Models;
|
using MvcMusicStore.Models;
|
||||||
|
|
||||||
|
|
@ -8,28 +8,24 @@ namespace MvcMusicStore.Controllers
|
||||||
{
|
{
|
||||||
public class HomeController : Controller
|
public class HomeController : Controller
|
||||||
{
|
{
|
||||||
private MusicStoreEntities storeDB = new MusicStoreEntities();
|
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||||
//
|
|
||||||
// GET: /Home/
|
// GET: /Home/
|
||||||
|
public async Task<ActionResult> Index()
|
||||||
public ActionResult Index()
|
|
||||||
{
|
{
|
||||||
// Get most popular albums
|
return View(await _storeContext.Albums
|
||||||
var albums = GetTopSellingAlbums(6);
|
.OrderByDescending(a => a.OrderDetails.Count())
|
||||||
|
.Take(6)
|
||||||
return View(albums);
|
.ToListAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
private List<Album> GetTopSellingAlbums(int count)
|
|
||||||
{
|
{
|
||||||
// Group the order details by album and return
|
if (disposing)
|
||||||
// the albums with the highest count
|
{
|
||||||
|
_storeContext.Dispose();
|
||||||
return storeDB.Albums
|
}
|
||||||
.OrderByDescending(a => a.OrderDetails.Count())
|
base.Dispose(disposing);
|
||||||
.Take(count)
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
using System.Linq;
|
using System.Data.Entity;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using MvcMusicStore.Models;
|
using MvcMusicStore.Models;
|
||||||
using MvcMusicStore.ViewModels;
|
using MvcMusicStore.ViewModels;
|
||||||
|
|
@ -7,75 +9,56 @@ namespace MvcMusicStore.Controllers
|
||||||
{
|
{
|
||||||
public class ShoppingCartController : Controller
|
public class ShoppingCartController : Controller
|
||||||
{
|
{
|
||||||
MusicStoreEntities storeDB = new MusicStoreEntities();
|
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /ShoppingCart/
|
// GET: /ShoppingCart/
|
||||||
|
public async Task<ActionResult> Index()
|
||||||
public ActionResult Index()
|
|
||||||
{
|
{
|
||||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
var cart = ShoppingCart.GetCart(_storeContext, this);
|
||||||
|
|
||||||
// Set up our ViewModel
|
|
||||||
var viewModel = new ShoppingCartViewModel
|
var viewModel = new ShoppingCartViewModel
|
||||||
{
|
{
|
||||||
CartItems = cart.GetCartItems(),
|
CartItems = await cart.GetCartItems().ToListAsync(),
|
||||||
CartTotal = cart.GetTotal()
|
CartTotal = await cart.GetTotal()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the view
|
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /ShoppingCart/AddToCart/5
|
// GET: /ShoppingCart/AddToCart/5
|
||||||
|
public async Task<ActionResult> AddToCart(int id)
|
||||||
public ActionResult AddToCart(int id)
|
|
||||||
{
|
{
|
||||||
|
var cart = ShoppingCart.GetCart(_storeContext, this);
|
||||||
|
|
||||||
// Retrieve the album from the database
|
await cart.AddToCart(await _storeContext.Albums.SingleAsync(a => a.AlbumId == id));
|
||||||
var addedAlbum = storeDB.Albums
|
|
||||||
.Single(album => album.AlbumId == id);
|
|
||||||
|
|
||||||
// Add it to the shopping cart
|
await _storeContext.SaveChangesAsync();
|
||||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
|
||||||
|
|
||||||
cart.AddToCart(addedAlbum);
|
|
||||||
|
|
||||||
storeDB.SaveChanges();
|
|
||||||
|
|
||||||
// Go back to the main store page for more shopping
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// AJAX: /ShoppingCart/RemoveFromCart/5
|
// AJAX: /ShoppingCart/RemoveFromCart/5
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public ActionResult RemoveFromCart(int id)
|
public async Task<ActionResult> RemoveFromCart(int id)
|
||||||
{
|
{
|
||||||
// Retrieve the current user's shopping cart
|
var cart = ShoppingCart.GetCart(_storeContext, this);
|
||||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
|
||||||
|
|
||||||
// Get the name of the album to display confirmation
|
var albumName = await _storeContext.Carts
|
||||||
string albumName = storeDB.Carts
|
.Where(i => i.RecordId == id)
|
||||||
.Single(item => item.RecordId == id).Album.Title;
|
.Select(i => i.Album.Title)
|
||||||
|
.SingleOrDefaultAsync();
|
||||||
|
|
||||||
// Remove from cart
|
var itemCount = await cart.RemoveFromCart(id);
|
||||||
int itemCount = cart.RemoveFromCart(id);
|
|
||||||
|
|
||||||
storeDB.SaveChanges();
|
await _storeContext.SaveChangesAsync();
|
||||||
|
|
||||||
string removed = (itemCount > 0) ? " 1 copy of " : string.Empty;
|
var removed = (itemCount > 0) ? " 1 copy of " : string.Empty;
|
||||||
|
|
||||||
// Display the confirmation message
|
|
||||||
|
|
||||||
var results = new ShoppingCartRemoveViewModel
|
var results = new ShoppingCartRemoveViewModel
|
||||||
{
|
{
|
||||||
Message = removed + albumName +
|
Message = removed + albumName + " has been removed from your shopping cart.",
|
||||||
" has been removed from your shopping cart.",
|
CartTotal = await cart.GetTotal(),
|
||||||
CartTotal = cart.GetTotal(),
|
CartCount = await cart.GetCount(),
|
||||||
CartCount = cart.GetCount(),
|
|
||||||
ItemCount = itemCount,
|
ItemCount = itemCount,
|
||||||
DeleteId = id
|
DeleteId = id
|
||||||
};
|
};
|
||||||
|
|
@ -86,16 +69,26 @@ namespace MvcMusicStore.Controllers
|
||||||
[ChildActionOnly]
|
[ChildActionOnly]
|
||||||
public ActionResult CartSummary()
|
public ActionResult CartSummary()
|
||||||
{
|
{
|
||||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
var cart = ShoppingCart.GetCart(_storeContext, this);
|
||||||
|
|
||||||
var cartItems = cart.GetCartItems()
|
var cartItems = cart.GetCartItems()
|
||||||
.Select(a => a.Album.Title)
|
.Select(a => a.Album.Title)
|
||||||
.OrderBy(x => x);
|
.OrderBy(x => x)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
ViewBag.CartCount = cartItems.Count();
|
ViewBag.CartCount = cartItems.Count();
|
||||||
ViewBag.CartSummary = string.Join("\n", cartItems.Distinct());
|
ViewBag.CartSummary = string.Join("\n", cartItems.Distinct());
|
||||||
|
|
||||||
return PartialView("CartSummary");
|
return PartialView("CartSummary");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_storeContext.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,57 +1,49 @@
|
||||||
using MvcMusicStore.Models;
|
using System.Data.Entity;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web;
|
using System.Threading.Tasks;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
using MvcMusicStore.Models;
|
||||||
|
|
||||||
namespace MvcMusicStore.Controllers
|
namespace MvcMusicStore.Controllers
|
||||||
{
|
{
|
||||||
public class StoreController : Controller
|
public class StoreController : Controller
|
||||||
{
|
{
|
||||||
MusicStoreEntities storeDB = new MusicStoreEntities();
|
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||||
//
|
|
||||||
// GET: /Store/
|
// GET: /Store/
|
||||||
|
public async Task<ActionResult> Index()
|
||||||
public ActionResult Index()
|
|
||||||
{
|
{
|
||||||
var genres = storeDB.Genres.ToList();
|
return View(await _storeContext.Genres.ToListAsync());
|
||||||
|
|
||||||
return View(genres);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /Store/Browse?genre=Disco
|
// GET: /Store/Browse?genre=Disco
|
||||||
|
public async Task<ActionResult> Browse(string genre)
|
||||||
public ActionResult Browse(string genre)
|
|
||||||
{
|
{
|
||||||
// Retrieve Genre genre and its Associated associated Albums albums from database
|
return View(await _storeContext.Genres.Include("Albums").SingleAsync(g => g.Name == genre));
|
||||||
var genreModel = storeDB.Genres.Include("Albums")
|
|
||||||
.Single(g => g.Name == genre);
|
|
||||||
|
|
||||||
return View(genreModel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult Details(int id)
|
public async Task<ActionResult> Details(int id)
|
||||||
{
|
{
|
||||||
var album = storeDB.Albums.Find(id);
|
var album = await _storeContext.Albums.FindAsync(id);
|
||||||
|
|
||||||
return View(album);
|
return album != null ? View(album) : (ActionResult)HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
[ChildActionOnly]
|
[ChildActionOnly]
|
||||||
public ActionResult GenreMenu()
|
public ActionResult GenreMenu()
|
||||||
{
|
{
|
||||||
var genres = storeDB.Genres
|
return PartialView(
|
||||||
.OrderByDescending(
|
_storeContext.Genres.OrderByDescending(
|
||||||
g => g.Albums.Sum(
|
g => g.Albums.Sum(a => a.OrderDetails.Sum(od => od.Quantity))).Take(9).ToList());
|
||||||
a => a.OrderDetails.Sum(
|
}
|
||||||
od => od.Quantity)))
|
|
||||||
.Take(9)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return PartialView(genres);
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_storeContext.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
using System;
|
using System.Data.Entity;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Data.Entity;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Web;
|
using System.Threading.Tasks;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
using MvcMusicStore.Models;
|
using MvcMusicStore.Models;
|
||||||
|
|
||||||
|
|
@ -12,119 +9,132 @@ namespace MvcMusicStore.Controllers
|
||||||
[Authorize(Roles = "Administrator")]
|
[Authorize(Roles = "Administrator")]
|
||||||
public class StoreManagerController : Controller
|
public class StoreManagerController : Controller
|
||||||
{
|
{
|
||||||
private MusicStoreEntities db = new MusicStoreEntities();
|
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /StoreManager/
|
// GET: /StoreManager/
|
||||||
|
public async Task<ActionResult> Index()
|
||||||
public ActionResult Index()
|
|
||||||
{
|
{
|
||||||
var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist)
|
return View(await _storeContext.Albums
|
||||||
.OrderBy(a => a.Price);
|
.Include(a => a.Genre)
|
||||||
return View(albums.ToList());
|
.Include(a => a.Artist)
|
||||||
|
.OrderBy(a => a.Price).ToListAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /StoreManager/Details/5
|
// GET: /StoreManager/Details/5
|
||||||
|
public async Task<ActionResult> Details(int id = 0)
|
||||||
public ActionResult Details(int id = 0)
|
|
||||||
{
|
{
|
||||||
Album album = db.Albums.Find(id);
|
var album = await _storeContext.Albums.FindAsync(id);
|
||||||
|
|
||||||
if (album == null)
|
if (album == null)
|
||||||
{
|
{
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
return View(album);
|
return View(album);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /StoreManager/Create
|
// GET: /StoreManager/Create
|
||||||
|
public async Task<ActionResult> Create()
|
||||||
public ActionResult Create()
|
|
||||||
{
|
{
|
||||||
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");
|
return await BuildView(null);
|
||||||
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
|
|
||||||
return View();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /StoreManager/Create
|
// POST: /StoreManager/Create
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public ActionResult Create(Album album)
|
public async Task<ActionResult> Create(Album album)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
db.Albums.Add(album);
|
_storeContext.Albums.Add(album);
|
||||||
db.SaveChanges();
|
|
||||||
|
await _storeContext.SaveChangesAsync();
|
||||||
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
|
return await BuildView(album);
|
||||||
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
|
|
||||||
return View(album);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /StoreManager/Edit/5
|
// GET: /StoreManager/Edit/5
|
||||||
|
public async Task<ActionResult> Edit(int id = 0)
|
||||||
public ActionResult Edit(int id = 0)
|
|
||||||
{
|
{
|
||||||
Album album = db.Albums.Find(id);
|
var album = await _storeContext.Albums.FindAsync(id);
|
||||||
if (album == null)
|
if (album == null)
|
||||||
{
|
{
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
|
|
||||||
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
|
return await BuildView(album);
|
||||||
return View(album);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /StoreManager/Edit/5
|
// POST: /StoreManager/Edit/5
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public ActionResult Edit(Album album)
|
public async Task<ActionResult> Edit(Album album)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
db.Entry(album).State = EntityState.Modified;
|
_storeContext.Entry(album).State = EntityState.Modified;
|
||||||
db.SaveChanges();
|
|
||||||
|
await _storeContext.SaveChangesAsync();
|
||||||
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
|
|
||||||
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
|
return await BuildView(album);
|
||||||
return View(album);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// GET: /StoreManager/Delete/5
|
// GET: /StoreManager/Delete/5
|
||||||
|
public async Task<ActionResult> Delete(int id = 0)
|
||||||
public ActionResult Delete(int id = 0)
|
|
||||||
{
|
{
|
||||||
Album album = db.Albums.Find(id);
|
var album = await _storeContext.Albums.FindAsync(id);
|
||||||
if (album == null)
|
if (album == null)
|
||||||
{
|
{
|
||||||
return HttpNotFound();
|
return HttpNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
return View(album);
|
return View(album);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// POST: /StoreManager/Delete/5
|
// POST: /StoreManager/Delete/5
|
||||||
|
|
||||||
[HttpPost, ActionName("Delete")]
|
[HttpPost, ActionName("Delete")]
|
||||||
public ActionResult DeleteConfirmed(int id)
|
public async Task<ActionResult> DeleteConfirmed(int id)
|
||||||
{
|
{
|
||||||
Album album = db.Albums.Find(id);
|
var album = await _storeContext.Albums.FindAsync(id);
|
||||||
db.Albums.Remove(album);
|
if (album == null)
|
||||||
db.SaveChanges();
|
{
|
||||||
|
return HttpNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
_storeContext.Albums.Remove(album);
|
||||||
|
|
||||||
|
await _storeContext.SaveChangesAsync();
|
||||||
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<ActionResult> BuildView(Album album)
|
||||||
|
{
|
||||||
|
ViewBag.GenreId = new SelectList(
|
||||||
|
await _storeContext.Genres.ToListAsync(),
|
||||||
|
"GenreId",
|
||||||
|
"Name",
|
||||||
|
album == null ? null : (object)album.GenreId);
|
||||||
|
|
||||||
|
ViewBag.ArtistId = new SelectList(
|
||||||
|
await _storeContext.Artists.ToListAsync(),
|
||||||
|
"ArtistId",
|
||||||
|
"Name",
|
||||||
|
album == null ? null : (object)album.ArtistId);
|
||||||
|
|
||||||
|
return View(album);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
db.Dispose();
|
if (disposing)
|
||||||
|
{
|
||||||
|
_storeContext.Dispose();
|
||||||
|
}
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@ namespace MvcMusicStore
|
||||||
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
|
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
|
||||||
RouteConfig.RegisterRoutes(RouteTable.Routes);
|
RouteConfig.RegisterRoutes(RouteTable.Routes);
|
||||||
BundleConfig.RegisterBundles(BundleTable.Bundles);
|
BundleConfig.RegisterBundles(BundleTable.Bundles);
|
||||||
|
|
||||||
System.Data.Entity.Database.SetInitializer(new MvcMusicStore.Models.SampleData());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,11 @@ namespace MvcMusicStore.Models
|
||||||
{
|
{
|
||||||
public class MusicStoreEntities : DbContext
|
public class MusicStoreEntities : DbContext
|
||||||
{
|
{
|
||||||
|
public MusicStoreEntities()
|
||||||
|
: base("name=MusicStoreEntities")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public DbSet<Album> Albums { get; set; }
|
public DbSet<Album> Albums { get; set; }
|
||||||
public DbSet<Genre> Genres { get; set; }
|
public DbSet<Genre> Genres { get; set; }
|
||||||
public DbSet<Artist> Artists { get; set; }
|
public DbSet<Artist> Artists { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ namespace MvcMusicStore.Models
|
||||||
[Bind(Include = "FirstName,LastName,Address,City,State,PostalCode,Country,Phone,Email")]
|
[Bind(Include = "FirstName,LastName,Address,City,State,PostalCode,Country,Phone,Email")]
|
||||||
public class Order
|
public class Order
|
||||||
{
|
{
|
||||||
|
public Order()
|
||||||
|
{
|
||||||
|
OrderDetails = new List<OrderDetail>();
|
||||||
|
}
|
||||||
|
|
||||||
[ScaffoldColumn(false)]
|
[ScaffoldColumn(false)]
|
||||||
public int OrderId { get; set; }
|
public int OrderId { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,195 +1,159 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Entity;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
|
|
||||||
namespace MvcMusicStore.Models
|
namespace MvcMusicStore.Models
|
||||||
{
|
{
|
||||||
public partial class ShoppingCart
|
public class ShoppingCart
|
||||||
{
|
{
|
||||||
MusicStoreEntities _db;
|
|
||||||
string ShoppingCartId { get; set; }
|
|
||||||
|
|
||||||
public ShoppingCart(MusicStoreEntities db)
|
|
||||||
{
|
|
||||||
_db = db;
|
|
||||||
}
|
|
||||||
|
|
||||||
public const string CartSessionKey = "CartId";
|
public const string CartSessionKey = "CartId";
|
||||||
|
|
||||||
public static ShoppingCart GetCart(MusicStoreEntities db, HttpContextBase context)
|
private readonly MusicStoreEntities _storeContext;
|
||||||
|
private readonly string _cartId;
|
||||||
|
|
||||||
|
private ShoppingCart(MusicStoreEntities storeContext, string cartId)
|
||||||
{
|
{
|
||||||
var cart = new ShoppingCart(db);
|
_storeContext = storeContext;
|
||||||
cart.ShoppingCartId = cart.GetCartId(context);
|
_cartId = cartId;
|
||||||
return cart;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method to simplify shopping cart calls
|
public static ShoppingCart GetCart(MusicStoreEntities storeContext, Controller controller)
|
||||||
public static ShoppingCart GetCart(MusicStoreEntities db, Controller controller)
|
|
||||||
{
|
{
|
||||||
return GetCart(db, controller.HttpContext);
|
return new ShoppingCart(storeContext, GetCartId(controller.HttpContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddToCart(Album album)
|
private static string GetCartId(HttpContextBase context)
|
||||||
{
|
|
||||||
// Get the matching cart and album instances
|
|
||||||
var cartItem = _db.Carts.SingleOrDefault(
|
|
||||||
c => c.CartId == ShoppingCartId
|
|
||||||
&& c.AlbumId == album.AlbumId);
|
|
||||||
|
|
||||||
if (cartItem == null)
|
|
||||||
{
|
|
||||||
// Create a new cart item if no cart item exists
|
|
||||||
cartItem = new Cart
|
|
||||||
{
|
|
||||||
AlbumId = album.AlbumId,
|
|
||||||
CartId = ShoppingCartId,
|
|
||||||
Count = 1,
|
|
||||||
DateCreated = DateTime.Now
|
|
||||||
};
|
|
||||||
|
|
||||||
_db.Carts.Add(cartItem);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the item does exist in the cart, then add one to the quantity
|
|
||||||
cartItem.Count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RemoveFromCart(int id)
|
|
||||||
{
|
|
||||||
// Get the cart
|
|
||||||
var cartItem = _db.Carts.Single(
|
|
||||||
cart => cart.CartId == ShoppingCartId
|
|
||||||
&& cart.RecordId == id);
|
|
||||||
|
|
||||||
int itemCount = 0;
|
|
||||||
|
|
||||||
if (cartItem != null)
|
|
||||||
{
|
|
||||||
if (cartItem.Count > 1)
|
|
||||||
{
|
|
||||||
cartItem.Count--;
|
|
||||||
itemCount = cartItem.Count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_db.Carts.Remove(cartItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return itemCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EmptyCart()
|
|
||||||
{
|
|
||||||
var cartItems = _db.Carts.Where(cart => cart.CartId == ShoppingCartId);
|
|
||||||
|
|
||||||
foreach (var cartItem in cartItems)
|
|
||||||
{
|
|
||||||
_db.Carts.Remove(cartItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Cart> GetCartItems()
|
|
||||||
{
|
|
||||||
return _db.Carts.Where(cart => cart.CartId == ShoppingCartId).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetCount()
|
|
||||||
{
|
|
||||||
// Get the count of each item in the cart and sum them up
|
|
||||||
int? count = (from cartItems in _db.Carts
|
|
||||||
where cartItems.CartId == ShoppingCartId
|
|
||||||
select (int?)cartItems.Count).Sum();
|
|
||||||
|
|
||||||
// Return 0 if all entries are null
|
|
||||||
return count ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public decimal GetTotal()
|
|
||||||
{
|
|
||||||
// Multiply album price by count of that album to get
|
|
||||||
// the current price for each of those albums in the cart
|
|
||||||
// sum all album price totals to get the cart total
|
|
||||||
decimal? total = (from cartItems in _db.Carts
|
|
||||||
where cartItems.CartId == ShoppingCartId
|
|
||||||
select (int?)cartItems.Count * cartItems.Album.Price).Sum();
|
|
||||||
return total ?? decimal.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CreateOrder(Order order)
|
|
||||||
{
|
|
||||||
decimal orderTotal = 0;
|
|
||||||
|
|
||||||
var cartItems = GetCartItems();
|
|
||||||
|
|
||||||
// Iterate over the items in the cart, adding the order details for each
|
|
||||||
foreach (var item in cartItems)
|
|
||||||
{
|
|
||||||
var album = _db.Albums.Find(item.AlbumId);
|
|
||||||
|
|
||||||
var orderDetail = new OrderDetail
|
|
||||||
{
|
|
||||||
AlbumId = item.AlbumId,
|
|
||||||
OrderId = order.OrderId,
|
|
||||||
UnitPrice = album.Price,
|
|
||||||
Quantity = item.Count,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set the order total of the shopping cart
|
|
||||||
orderTotal += (item.Count * item.Album.Price);
|
|
||||||
|
|
||||||
_db.OrderDetails.Add(orderDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the order's total to the orderTotal count
|
|
||||||
order.Total = orderTotal;
|
|
||||||
|
|
||||||
// Empty the shopping cart
|
|
||||||
EmptyCart();
|
|
||||||
|
|
||||||
// Return the OrderId as the confirmation number
|
|
||||||
return order.OrderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're using HttpContextBase to allow access to cookies.
|
|
||||||
public string GetCartId(HttpContextBase context)
|
|
||||||
{
|
{
|
||||||
if (context.Session[CartSessionKey] == null)
|
if (context.Session[CartSessionKey] == null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(context.User.Identity.Name))
|
var username = context.User.Identity.Name;
|
||||||
{
|
|
||||||
context.Session[CartSessionKey] = context.User.Identity.Name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Generate a new random GUID using System.Guid class
|
|
||||||
Guid tempCartId = Guid.NewGuid();
|
|
||||||
|
|
||||||
// Send tempCartId back to client as a cookie
|
context.Session[CartSessionKey] = !string.IsNullOrWhiteSpace(username)
|
||||||
context.Session[CartSessionKey] = tempCartId.ToString();
|
? username
|
||||||
}
|
: Guid.NewGuid().ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.Session[CartSessionKey].ToString();
|
return context.Session[CartSessionKey].ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// When a user has logged in, migrate their shopping cart to
|
public async Task AddToCart(Album album)
|
||||||
// be associated with their username
|
|
||||||
public void MigrateCart(string userName)
|
|
||||||
{
|
{
|
||||||
var shoppingCart = _db.Carts.Where(c => c.CartId == ShoppingCartId);
|
var cartItem = await GetCartItem(album.AlbumId);
|
||||||
|
|
||||||
foreach (Cart item in shoppingCart)
|
if (cartItem == null)
|
||||||
|
{
|
||||||
|
cartItem = new Cart
|
||||||
|
{
|
||||||
|
AlbumId = album.AlbumId,
|
||||||
|
CartId = _cartId,
|
||||||
|
Count = 1,
|
||||||
|
DateCreated = DateTime.Now
|
||||||
|
};
|
||||||
|
|
||||||
|
_storeContext.Carts.Add(cartItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cartItem.Count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> RemoveFromCart(int id)
|
||||||
|
{
|
||||||
|
var cartItem = await GetCartItem(id);
|
||||||
|
|
||||||
|
if (cartItem != null)
|
||||||
|
{
|
||||||
|
if (cartItem.Count > 1)
|
||||||
|
{
|
||||||
|
return --cartItem.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
_storeContext.Carts.Remove(cartItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<Cart> GetCartItem(int albumId)
|
||||||
|
{
|
||||||
|
return _storeContext.Carts.SingleOrDefaultAsync(
|
||||||
|
c => c.CartId == _cartId && c.AlbumId == albumId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQueryable<Cart> GetCartItems()
|
||||||
|
{
|
||||||
|
return _storeContext.Carts.Where(c => c.CartId == _cartId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<int> GetCount()
|
||||||
|
{
|
||||||
|
return _storeContext.Carts
|
||||||
|
.Where(c => c.CartId == _cartId)
|
||||||
|
.Select(c => c.Count)
|
||||||
|
.SumAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<decimal> GetTotal()
|
||||||
|
{
|
||||||
|
return _storeContext.Carts
|
||||||
|
.Where(c => c.CartId == _cartId)
|
||||||
|
.Select(c => c.Count * c.Album.Price)
|
||||||
|
.SumAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> CreateOrder(Order order)
|
||||||
|
{
|
||||||
|
decimal orderTotal = 0;
|
||||||
|
|
||||||
|
var cartItems = await _storeContext.Carts
|
||||||
|
.Where(c => c.CartId == _cartId)
|
||||||
|
.Include(c => c.Album)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
foreach (var item in cartItems)
|
||||||
|
{
|
||||||
|
order.OrderDetails.Add(new OrderDetail
|
||||||
|
{
|
||||||
|
AlbumId = item.AlbumId,
|
||||||
|
OrderId = order.OrderId,
|
||||||
|
UnitPrice = item.Album.Price,
|
||||||
|
Quantity = item.Count,
|
||||||
|
});
|
||||||
|
|
||||||
|
orderTotal += item.Count * item.Album.Price;
|
||||||
|
}
|
||||||
|
|
||||||
|
order.Total = orderTotal;
|
||||||
|
|
||||||
|
await EmptyCart();
|
||||||
|
|
||||||
|
return order.OrderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task EmptyCart()
|
||||||
|
{
|
||||||
|
foreach (var cartItem in await _storeContext.Carts.Where(
|
||||||
|
c => c.CartId == _cartId).ToListAsync())
|
||||||
|
{
|
||||||
|
_storeContext.Carts.Remove(cartItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task MigrateCart(string userName)
|
||||||
|
{
|
||||||
|
var carts = await _storeContext.Carts.Where(c => c.CartId == _cartId).ToListAsync();
|
||||||
|
|
||||||
|
foreach (var item in carts)
|
||||||
{
|
{
|
||||||
item.CartId = userName;
|
item.CartId = userName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _storeContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||||
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
|
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
|
||||||
<connectionStrings>
|
<connectionStrings>
|
||||||
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-MvcMusicStore-20131025034205.mdf;Initial Catalog=aspnet-MvcMusicStore-20131025034205;Integrated Security=True" providerName="System.Data.SqlClient" />
|
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcMusicStore-20131025034205;Integrated Security=True" providerName="System.Data.SqlClient" />
|
||||||
<add name="MusicStoreEntities" connectionString="Data Source=(LocalDB)\v11.0; AttachDbFilename=|DataDirectory|\MvcMusicStore.mdf; Integrated Security=True" providerName="System.Data.SqlClient" />
|
<add name="MusicStoreEntities" connectionString="Data Source=(LocalDB)\v11.0;Initial Catalog=MusicStore;Integrated Security=True" providerName="System.Data.SqlClient" />
|
||||||
</connectionStrings>
|
</connectionStrings>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<add key="DefaultAdminUsername" value="Administrator" />
|
<add key="DefaultAdminUsername" value="Administrator" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue