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:
parent
53268f3c9e
commit
6a9b6c16c2
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Sake" version="0.2" />
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Sake" version="0.2" />
|
||||
</packages>
|
||||
|
|
@ -9,6 +9,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MusicStore.k10", "src\Music
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MusicStore.net45", "src\MusicStore\MusicStore.net45.csproj", "{9C8A2D1F-D430-46DF-8F00-39E378EC8FB2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{44621553-AA7D-4893-8834-79582A7D8348}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.nuget\packages.config = .nuget\packages.config
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
|
|||
|
|
@ -1,46 +1,53 @@
|
|||
using Microsoft.AspNet.Identity;
|
||||
using System.Configuration;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Identity.EntityFramework;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Security.Cookies;
|
||||
using MvcMusicStore.Models;
|
||||
using Owin;
|
||||
using System.Configuration;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MvcMusicStore
|
||||
{
|
||||
public partial class Startup
|
||||
{
|
||||
private const string RoleName = "Administrator";
|
||||
|
||||
public void ConfigureApp(IAppBuilder app)
|
||||
{
|
||||
System.Data.Entity.Database.SetInitializer(new MvcMusicStore.Models.SampleData());
|
||||
using (var context = new MusicStoreEntities())
|
||||
{
|
||||
context.Database.Delete();
|
||||
context.Database.Create();
|
||||
|
||||
new SampleData().Seed(context);
|
||||
}
|
||||
|
||||
CreateAdminUser();
|
||||
}
|
||||
|
||||
private async void CreateAdminUser()
|
||||
{
|
||||
string _username = ConfigurationManager.AppSettings["DefaultAdminUsername"];
|
||||
string _password = ConfigurationManager.AppSettings["DefaultAdminPassword"];
|
||||
string _role = "Administrator";
|
||||
var username = ConfigurationManager.AppSettings["DefaultAdminUsername"];
|
||||
var password = ConfigurationManager.AppSettings["DefaultAdminPassword"];
|
||||
|
||||
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)
|
||||
using (var context = new ApplicationDbContext())
|
||||
{
|
||||
await roleManager.CreateAsync(role);
|
||||
}
|
||||
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
|
||||
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
|
||||
|
||||
var user = await userManager.FindByNameAsync(_username);
|
||||
if (user == null)
|
||||
{
|
||||
user = new ApplicationUser { UserName = _username };
|
||||
await userManager.CreateAsync(user, _password);
|
||||
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.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Identity.EntityFramework;
|
||||
using Microsoft.AspNet.Identity.Owin;
|
||||
using Microsoft.Owin.Security;
|
||||
using MvcMusicStore.Models;
|
||||
|
||||
|
|
@ -15,6 +14,18 @@ namespace MvcMusicStore.Controllers
|
|||
[Authorize]
|
||||
public class AccountController : Controller
|
||||
{
|
||||
public enum ManageMessageId
|
||||
{
|
||||
ChangePasswordSuccess,
|
||||
SetPasswordSuccess,
|
||||
RemoveLoginSuccess,
|
||||
Error
|
||||
}
|
||||
|
||||
private const string XsrfKey = "XsrfId";
|
||||
|
||||
private UserManager<ApplicationUser> _userManager;
|
||||
|
||||
public AccountController()
|
||||
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
|
||||
{
|
||||
|
|
@ -22,33 +33,35 @@ namespace MvcMusicStore.Controllers
|
|||
|
||||
public AccountController(UserManager<ApplicationUser> userManager)
|
||||
{
|
||||
UserManager = userManager;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
public UserManager<ApplicationUser> UserManager { get; private set; }
|
||||
|
||||
private void MigrateShoppingCart(string UserName)
|
||||
private IAuthenticationManager AuthenticationManager
|
||||
{
|
||||
var storeDb = new MusicStoreEntities();
|
||||
|
||||
// Associate shopping cart items with logged-in user
|
||||
var cart = ShoppingCart.GetCart(storeDb, this.HttpContext);
|
||||
cart.MigrateCart(UserName);
|
||||
storeDb.SaveChanges();
|
||||
|
||||
Session[ShoppingCart.CartSessionKey] = UserName;
|
||||
get { return HttpContext.GetOwinContext().Authentication; }
|
||||
}
|
||||
|
||||
private async Task MigrateShoppingCart(string userName)
|
||||
{
|
||||
using (var storeContext = new MusicStoreEntities())
|
||||
{
|
||||
var cart = ShoppingCart.GetCart(storeContext, this);
|
||||
|
||||
await cart.MigrateCart(userName);
|
||||
|
||||
Session[ShoppingCart.CartSessionKey] = userName;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Login
|
||||
[AllowAnonymous]
|
||||
public ActionResult Login(string returnUrl)
|
||||
{
|
||||
ViewBag.ReturnUrl = returnUrl;
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/Login
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
|
|
@ -57,23 +70,20 @@ namespace MvcMusicStore.Controllers
|
|||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = await UserManager.FindAsync(model.UserName, model.Password);
|
||||
var user = await _userManager.FindAsync(model.UserName, model.Password);
|
||||
if (user != null)
|
||||
{
|
||||
await SignInAsync(user, model.RememberMe);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Register
|
||||
[AllowAnonymous]
|
||||
public ActionResult Register()
|
||||
|
|
@ -81,7 +91,6 @@ namespace MvcMusicStore.Controllers
|
|||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/Register
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
|
|
@ -90,85 +99,84 @@ namespace MvcMusicStore.Controllers
|
|||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = new ApplicationUser() { UserName = model.UserName };
|
||||
var result = await UserManager.CreateAsync(user, model.Password);
|
||||
var user = new ApplicationUser { UserName = model.UserName };
|
||||
var result = await _userManager.CreateAsync(user, model.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await SignInAsync(user, isPersistent: false);
|
||||
await SignInAsync(user, false);
|
||||
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/Disassociate
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
|
||||
{
|
||||
ManageMessageId? message = null;
|
||||
IdentityResult result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
|
||||
if (result.Succeeded)
|
||||
{
|
||||
message = ManageMessageId.RemoveLoginSuccess;
|
||||
}
|
||||
else
|
||||
{
|
||||
message = ManageMessageId.Error;
|
||||
}
|
||||
return RedirectToAction("Manage", new { Message = message });
|
||||
var result = await _userManager.RemoveLoginAsync(
|
||||
User.Identity.GetUserId(),
|
||||
new UserLoginInfo(loginProvider, providerKey));
|
||||
|
||||
return RedirectToAction(
|
||||
"Manage",
|
||||
new { Message = result.Succeeded ? ManageMessageId.RemoveLoginSuccess : ManageMessageId.Error });
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Manage
|
||||
public ActionResult Manage(ManageMessageId? message)
|
||||
public async Task<ActionResult> Manage(ManageMessageId? message)
|
||||
{
|
||||
ViewBag.StatusMessage =
|
||||
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
|
||||
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
|
||||
: message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
|
||||
: message == ManageMessageId.Error ? "An error has occurred."
|
||||
: "";
|
||||
ViewBag.HasLocalPassword = HasPassword();
|
||||
message == ManageMessageId.ChangePasswordSuccess
|
||||
? "Your password has been changed."
|
||||
: message == ManageMessageId.SetPasswordSuccess
|
||||
? "Your password has been set."
|
||||
: message == ManageMessageId.RemoveLoginSuccess
|
||||
? "The external login was removed."
|
||||
: message == ManageMessageId.Error
|
||||
? "An error has occurred."
|
||||
: "";
|
||||
|
||||
ViewBag.HasLocalPassword = await HasPasswordAsync();
|
||||
ViewBag.ReturnUrl = Url.Action("Manage");
|
||||
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/Manage
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<ActionResult> Manage(ManageUserViewModel model)
|
||||
{
|
||||
bool hasPassword = HasPassword();
|
||||
bool hasPassword = await HasPasswordAsync();
|
||||
ViewBag.HasLocalPassword = hasPassword;
|
||||
ViewBag.ReturnUrl = Url.Action("Manage");
|
||||
|
||||
if (hasPassword)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
|
||||
}
|
||||
else
|
||||
{
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
AddErrors(result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// User does not have a password so remove any validation errors caused by a missing OldPassword field
|
||||
ModelState state = ModelState["OldPassword"];
|
||||
var state = ModelState["OldPassword"];
|
||||
if (state != null)
|
||||
{
|
||||
state.Errors.Clear();
|
||||
|
|
@ -176,34 +184,32 @@ namespace MvcMusicStore.Controllers
|
|||
|
||||
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)
|
||||
{
|
||||
return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
|
||||
}
|
||||
else
|
||||
{
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
AddErrors(result);
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ExternalLogin
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public ActionResult ExternalLogin(string provider, string returnUrl)
|
||||
{
|
||||
// Request a redirect to the external login provider
|
||||
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
|
||||
return new ChallengeResult(provider,
|
||||
Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ExternalLoginCallback
|
||||
[AllowAnonymous]
|
||||
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
|
||||
|
|
@ -214,55 +220,56 @@ namespace MvcMusicStore.Controllers
|
|||
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)
|
||||
{
|
||||
await SignInAsync(user, isPersistent: false);
|
||||
await SignInAsync(user, false);
|
||||
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the user does not have an account, then prompt the user to create an account
|
||||
ViewBag.ReturnUrl = returnUrl;
|
||||
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
|
||||
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
|
||||
}
|
||||
|
||||
ViewBag.ReturnUrl = returnUrl;
|
||||
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
|
||||
|
||||
return View("ExternalLoginConfirmation",
|
||||
new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName });
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/LinkLogin
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
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());
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return RedirectToAction("Manage");
|
||||
}
|
||||
|
||||
return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ExternalLoginConfirmation
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
|
||||
public async Task<ActionResult> ExternalLoginConfirmation(
|
||||
ExternalLoginConfirmationViewModel model,
|
||||
string returnUrl)
|
||||
{
|
||||
if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
|
|
@ -277,35 +284,39 @@ namespace MvcMusicStore.Controllers
|
|||
{
|
||||
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)
|
||||
{
|
||||
result = await UserManager.AddLoginAsync(user.Id, info.Login);
|
||||
result = await _userManager.AddLoginAsync(user.Id, info.Login);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
await SignInAsync(user, isPersistent: false);
|
||||
await SignInAsync(user, false);
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
}
|
||||
|
||||
AddErrors(result);
|
||||
}
|
||||
|
||||
ViewBag.ReturnUrl = returnUrl;
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/LogOff
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public ActionResult LogOff()
|
||||
{
|
||||
AuthenticationManager.SignOut();
|
||||
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ExternalLoginFailure
|
||||
[AllowAnonymous]
|
||||
public ActionResult ExternalLoginFailure()
|
||||
|
|
@ -316,41 +327,34 @@ namespace MvcMusicStore.Controllers
|
|||
[ChildActionOnly]
|
||||
public ActionResult RemoveAccountList()
|
||||
{
|
||||
var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId());
|
||||
var linkedAccounts = _userManager.GetLogins(User.Identity.GetUserId());
|
||||
|
||||
ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
|
||||
return (ActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
|
||||
|
||||
return PartialView("_RemoveAccountPartial", linkedAccounts);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && UserManager != null)
|
||||
if (disposing && _userManager != null)
|
||||
{
|
||||
UserManager.Dispose();
|
||||
UserManager = null;
|
||||
_userManager.Dispose();
|
||||
_userManager = null;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
MigrateShoppingCart(user.UserName);
|
||||
var identity =
|
||||
await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
|
||||
|
||||
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, identity);
|
||||
|
||||
await MigrateShoppingCart(user.UserName);
|
||||
}
|
||||
|
||||
private void AddErrors(IdentityResult result)
|
||||
|
|
@ -363,61 +367,47 @@ namespace MvcMusicStore.Controllers
|
|||
|
||||
private bool HasPassword()
|
||||
{
|
||||
var user = UserManager.FindById(User.Identity.GetUserId());
|
||||
if (user != null)
|
||||
{
|
||||
return user.PasswordHash != null;
|
||||
}
|
||||
return false;
|
||||
var user = _userManager.FindById(User.Identity.GetUserId());
|
||||
|
||||
return user != null && user.PasswordHash != null;
|
||||
}
|
||||
|
||||
public enum ManageMessageId
|
||||
private async Task<bool> HasPasswordAsync()
|
||||
{
|
||||
ChangePasswordSuccess,
|
||||
SetPasswordSuccess,
|
||||
RemoveLoginSuccess,
|
||||
Error
|
||||
var user = await _userManager.FindByIdAsync(User.Identity.GetUserId());
|
||||
|
||||
return user != null && user.PasswordHash != null;
|
||||
}
|
||||
|
||||
private ActionResult RedirectToLocal(string returnUrl)
|
||||
{
|
||||
if (Url.IsLocalUrl(returnUrl))
|
||||
{
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RedirectToAction("Index", "Home");
|
||||
}
|
||||
return Url.IsLocalUrl(returnUrl)
|
||||
? (ActionResult)Redirect(returnUrl)
|
||||
: RedirectToAction("Index", "Home");
|
||||
}
|
||||
|
||||
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;
|
||||
RedirectUri = redirectUri;
|
||||
UserId = userId;
|
||||
_loginProvider = provider;
|
||||
_redirectUri = redirectUri;
|
||||
_userId = userId;
|
||||
}
|
||||
|
||||
public string LoginProvider { get; set; }
|
||||
public string RedirectUri { get; set; }
|
||||
public string UserId { get; set; }
|
||||
|
||||
public override void ExecuteResult(ControllerContext context)
|
||||
{
|
||||
var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
|
||||
if (UserId != null)
|
||||
var properties = new AuthenticationProperties { RedirectUri = _redirectUri };
|
||||
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.Linq;
|
||||
using System.Data.Entity;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Mvc;
|
||||
using MvcMusicStore.Models;
|
||||
|
||||
|
|
@ -8,78 +9,56 @@ namespace MvcMusicStore.Controllers
|
|||
[Authorize]
|
||||
public class CheckoutController : Controller
|
||||
{
|
||||
MusicStoreEntities storeDB = new MusicStoreEntities();
|
||||
const string PromoCode = "FREE";
|
||||
private const string PromoCode = "FREE";
|
||||
|
||||
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||
|
||||
//
|
||||
// GET: /Checkout/
|
||||
|
||||
public ActionResult AddressAndPayment()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Checkout/AddressAndPayment
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult AddressAndPayment(FormCollection values)
|
||||
public async Task<ActionResult> AddressAndPayment(FormCollection values)
|
||||
{
|
||||
var order = new Order();
|
||||
TryUpdateModel(order);
|
||||
|
||||
try
|
||||
if (ModelState.IsValid
|
||||
&& string.Equals(values["PromoCode"], PromoCode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (string.Equals(values["PromoCode"], PromoCode,
|
||||
StringComparison.OrdinalIgnoreCase) == false)
|
||||
{
|
||||
return View(order);
|
||||
}
|
||||
else
|
||||
{
|
||||
order.Username = User.Identity.Name;
|
||||
order.OrderDate = DateTime.Now;
|
||||
order.Username = User.Identity.Name;
|
||||
order.OrderDate = DateTime.Now;
|
||||
|
||||
//Add the Order
|
||||
storeDB.Orders.Add(order);
|
||||
_storeContext.Orders.Add(order);
|
||||
|
||||
//Process the order
|
||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
||||
cart.CreateOrder(order);
|
||||
await ShoppingCart.GetCart(_storeContext, this).CreateOrder(order);
|
||||
|
||||
// Save all changes
|
||||
storeDB.SaveChanges();
|
||||
|
||||
return RedirectToAction("Complete",
|
||||
new { id = order.OrderId });
|
||||
}
|
||||
await _storeContext.SaveChangesAsync();
|
||||
|
||||
return RedirectToAction("Complete", new { id = order.OrderId });
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Invalid - redisplay with errors
|
||||
return View(order);
|
||||
}
|
||||
|
||||
return View(order);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Checkout/Complete
|
||||
|
||||
public ActionResult Complete(int id)
|
||||
public async Task<ActionResult> Complete(int id)
|
||||
{
|
||||
// Validate customer owns this order
|
||||
bool isValid = storeDB.Orders.Any(
|
||||
o => o.OrderId == id &&
|
||||
o.Username == User.Identity.Name);
|
||||
return await _storeContext.Orders.AnyAsync(o => o.OrderId == id && o.Username == User.Identity.Name)
|
||||
? View(id)
|
||||
: View("Error");
|
||||
}
|
||||
|
||||
if (isValid)
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
return View(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
return View("Error");
|
||||
_storeContext.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Mvc;
|
||||
using MvcMusicStore.Models;
|
||||
|
||||
|
|
@ -8,28 +8,24 @@ namespace MvcMusicStore.Controllers
|
|||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
private MusicStoreEntities storeDB = new MusicStoreEntities();
|
||||
//
|
||||
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||
|
||||
// GET: /Home/
|
||||
|
||||
public ActionResult Index()
|
||||
public async Task<ActionResult> Index()
|
||||
{
|
||||
// Get most popular albums
|
||||
var albums = GetTopSellingAlbums(6);
|
||||
|
||||
return View(albums);
|
||||
return View(await _storeContext.Albums
|
||||
.OrderByDescending(a => a.OrderDetails.Count())
|
||||
.Take(6)
|
||||
.ToListAsync());
|
||||
}
|
||||
|
||||
|
||||
private List<Album> GetTopSellingAlbums(int count)
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
// Group the order details by album and return
|
||||
// the albums with the highest count
|
||||
|
||||
return storeDB.Albums
|
||||
.OrderByDescending(a => a.OrderDetails.Count())
|
||||
.Take(count)
|
||||
.ToList();
|
||||
if (disposing)
|
||||
{
|
||||
_storeContext.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
using System.Linq;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Mvc;
|
||||
using MvcMusicStore.Models;
|
||||
using MvcMusicStore.ViewModels;
|
||||
|
|
@ -7,75 +9,56 @@ namespace MvcMusicStore.Controllers
|
|||
{
|
||||
public class ShoppingCartController : Controller
|
||||
{
|
||||
MusicStoreEntities storeDB = new MusicStoreEntities();
|
||||
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||
|
||||
//
|
||||
// GET: /ShoppingCart/
|
||||
|
||||
public ActionResult Index()
|
||||
public async Task<ActionResult> Index()
|
||||
{
|
||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
||||
var cart = ShoppingCart.GetCart(_storeContext, this);
|
||||
|
||||
// Set up our ViewModel
|
||||
var viewModel = new ShoppingCartViewModel
|
||||
{
|
||||
CartItems = cart.GetCartItems(),
|
||||
CartTotal = cart.GetTotal()
|
||||
CartItems = await cart.GetCartItems().ToListAsync(),
|
||||
CartTotal = await cart.GetTotal()
|
||||
};
|
||||
|
||||
// Return the view
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /ShoppingCart/AddToCart/5
|
||||
|
||||
public ActionResult AddToCart(int id)
|
||||
public async Task<ActionResult> AddToCart(int id)
|
||||
{
|
||||
var cart = ShoppingCart.GetCart(_storeContext, this);
|
||||
|
||||
// Retrieve the album from the database
|
||||
var addedAlbum = storeDB.Albums
|
||||
.Single(album => album.AlbumId == id);
|
||||
await cart.AddToCart(await _storeContext.Albums.SingleAsync(a => a.AlbumId == id));
|
||||
|
||||
// Add it to the shopping cart
|
||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
||||
await _storeContext.SaveChangesAsync();
|
||||
|
||||
cart.AddToCart(addedAlbum);
|
||||
|
||||
storeDB.SaveChanges();
|
||||
|
||||
// Go back to the main store page for more shopping
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
//
|
||||
// AJAX: /ShoppingCart/RemoveFromCart/5
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult RemoveFromCart(int id)
|
||||
public async Task<ActionResult> RemoveFromCart(int id)
|
||||
{
|
||||
// Retrieve the current user's shopping cart
|
||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
||||
var cart = ShoppingCart.GetCart(_storeContext, this);
|
||||
|
||||
// Get the name of the album to display confirmation
|
||||
string albumName = storeDB.Carts
|
||||
.Single(item => item.RecordId == id).Album.Title;
|
||||
var albumName = await _storeContext.Carts
|
||||
.Where(i => i.RecordId == id)
|
||||
.Select(i => i.Album.Title)
|
||||
.SingleOrDefaultAsync();
|
||||
|
||||
// Remove from cart
|
||||
int itemCount = cart.RemoveFromCart(id);
|
||||
var itemCount = await cart.RemoveFromCart(id);
|
||||
|
||||
storeDB.SaveChanges();
|
||||
await _storeContext.SaveChangesAsync();
|
||||
|
||||
string removed = (itemCount > 0) ? " 1 copy of " : string.Empty;
|
||||
|
||||
// Display the confirmation message
|
||||
var removed = (itemCount > 0) ? " 1 copy of " : string.Empty;
|
||||
|
||||
var results = new ShoppingCartRemoveViewModel
|
||||
{
|
||||
Message = removed + albumName +
|
||||
" has been removed from your shopping cart.",
|
||||
CartTotal = cart.GetTotal(),
|
||||
CartCount = cart.GetCount(),
|
||||
Message = removed + albumName + " has been removed from your shopping cart.",
|
||||
CartTotal = await cart.GetTotal(),
|
||||
CartCount = await cart.GetCount(),
|
||||
ItemCount = itemCount,
|
||||
DeleteId = id
|
||||
};
|
||||
|
|
@ -86,16 +69,26 @@ namespace MvcMusicStore.Controllers
|
|||
[ChildActionOnly]
|
||||
public ActionResult CartSummary()
|
||||
{
|
||||
var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
|
||||
var cart = ShoppingCart.GetCart(_storeContext, this);
|
||||
|
||||
var cartItems = cart.GetCartItems()
|
||||
.Select(a => a.Album.Title)
|
||||
.OrderBy(x => x);
|
||||
.OrderBy(x => x)
|
||||
.ToList();
|
||||
|
||||
ViewBag.CartCount = cartItems.Count();
|
||||
ViewBag.CartSummary = string.Join("\n", cartItems.Distinct());
|
||||
|
||||
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;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Mvc;
|
||||
using MvcMusicStore.Models;
|
||||
|
||||
namespace MvcMusicStore.Controllers
|
||||
{
|
||||
public class StoreController : Controller
|
||||
{
|
||||
MusicStoreEntities storeDB = new MusicStoreEntities();
|
||||
//
|
||||
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||
|
||||
// GET: /Store/
|
||||
|
||||
public ActionResult Index()
|
||||
public async Task<ActionResult> Index()
|
||||
{
|
||||
var genres = storeDB.Genres.ToList();
|
||||
|
||||
return View(genres);
|
||||
return View(await _storeContext.Genres.ToListAsync());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GET: /Store/Browse?genre=Disco
|
||||
|
||||
public ActionResult Browse(string genre)
|
||||
public async Task<ActionResult> Browse(string genre)
|
||||
{
|
||||
// Retrieve Genre genre and its Associated associated Albums albums from database
|
||||
var genreModel = storeDB.Genres.Include("Albums")
|
||||
.Single(g => g.Name == genre);
|
||||
|
||||
return View(genreModel);
|
||||
return View(await _storeContext.Genres.Include("Albums").SingleAsync(g => g.Name == genre));
|
||||
}
|
||||
|
||||
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]
|
||||
public ActionResult GenreMenu()
|
||||
{
|
||||
var genres = storeDB.Genres
|
||||
.OrderByDescending(
|
||||
g => g.Albums.Sum(
|
||||
a => a.OrderDetails.Sum(
|
||||
od => od.Quantity)))
|
||||
.Take(9)
|
||||
.ToList();
|
||||
return PartialView(
|
||||
_storeContext.Genres.OrderByDescending(
|
||||
g => g.Albums.Sum(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.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Entity;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Mvc;
|
||||
using MvcMusicStore.Models;
|
||||
|
||||
|
|
@ -12,119 +9,132 @@ namespace MvcMusicStore.Controllers
|
|||
[Authorize(Roles = "Administrator")]
|
||||
public class StoreManagerController : Controller
|
||||
{
|
||||
private MusicStoreEntities db = new MusicStoreEntities();
|
||||
private readonly MusicStoreEntities _storeContext = new MusicStoreEntities();
|
||||
|
||||
//
|
||||
// GET: /StoreManager/
|
||||
|
||||
public ActionResult Index()
|
||||
public async Task<ActionResult> Index()
|
||||
{
|
||||
var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist)
|
||||
.OrderBy(a => a.Price);
|
||||
return View(albums.ToList());
|
||||
return View(await _storeContext.Albums
|
||||
.Include(a => a.Genre)
|
||||
.Include(a => a.Artist)
|
||||
.OrderBy(a => a.Price).ToListAsync());
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /StoreManager/Details/5
|
||||
|
||||
public ActionResult Details(int id = 0)
|
||||
public async Task<ActionResult> Details(int id = 0)
|
||||
{
|
||||
Album album = db.Albums.Find(id);
|
||||
var album = await _storeContext.Albums.FindAsync(id);
|
||||
|
||||
if (album == null)
|
||||
{
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
return View(album);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /StoreManager/Create
|
||||
|
||||
public ActionResult Create()
|
||||
public async Task<ActionResult> Create()
|
||||
{
|
||||
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");
|
||||
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
|
||||
return View();
|
||||
return await BuildView(null);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /StoreManager/Create
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Create(Album album)
|
||||
public async Task<ActionResult> Create(Album album)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
db.Albums.Add(album);
|
||||
db.SaveChanges();
|
||||
_storeContext.Albums.Add(album);
|
||||
|
||||
await _storeContext.SaveChangesAsync();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
|
||||
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
|
||||
return View(album);
|
||||
return await BuildView(album);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /StoreManager/Edit/5
|
||||
|
||||
public ActionResult Edit(int id = 0)
|
||||
public async Task<ActionResult> Edit(int id = 0)
|
||||
{
|
||||
Album album = db.Albums.Find(id);
|
||||
var album = await _storeContext.Albums.FindAsync(id);
|
||||
if (album == null)
|
||||
{
|
||||
return HttpNotFound();
|
||||
}
|
||||
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
|
||||
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
|
||||
return View(album);
|
||||
|
||||
return await BuildView(album);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /StoreManager/Edit/5
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Edit(Album album)
|
||||
public async Task<ActionResult> Edit(Album album)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
db.Entry(album).State = EntityState.Modified;
|
||||
db.SaveChanges();
|
||||
_storeContext.Entry(album).State = EntityState.Modified;
|
||||
|
||||
await _storeContext.SaveChangesAsync();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
|
||||
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
|
||||
return View(album);
|
||||
|
||||
return await BuildView(album);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /StoreManager/Delete/5
|
||||
|
||||
public ActionResult Delete(int id = 0)
|
||||
public async Task<ActionResult> Delete(int id = 0)
|
||||
{
|
||||
Album album = db.Albums.Find(id);
|
||||
var album = await _storeContext.Albums.FindAsync(id);
|
||||
if (album == null)
|
||||
{
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
return View(album);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /StoreManager/Delete/5
|
||||
|
||||
[HttpPost, ActionName("Delete")]
|
||||
public ActionResult DeleteConfirmed(int id)
|
||||
public async Task<ActionResult> DeleteConfirmed(int id)
|
||||
{
|
||||
Album album = db.Albums.Find(id);
|
||||
db.Albums.Remove(album);
|
||||
db.SaveChanges();
|
||||
var album = await _storeContext.Albums.FindAsync(id);
|
||||
if (album == null)
|
||||
{
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
_storeContext.Albums.Remove(album);
|
||||
|
||||
await _storeContext.SaveChangesAsync();
|
||||
|
||||
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)
|
||||
{
|
||||
db.Dispose();
|
||||
if (disposing)
|
||||
{
|
||||
_storeContext.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@ namespace MvcMusicStore
|
|||
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
|
||||
RouteConfig.RegisterRoutes(RouteTable.Routes);
|
||||
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 MusicStoreEntities()
|
||||
: base("name=MusicStoreEntities")
|
||||
{
|
||||
}
|
||||
|
||||
public DbSet<Album> Albums { get; set; }
|
||||
public DbSet<Genre> Genres { 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")]
|
||||
public class Order
|
||||
{
|
||||
public Order()
|
||||
{
|
||||
OrderDetails = new List<OrderDetail>();
|
||||
}
|
||||
|
||||
[ScaffoldColumn(false)]
|
||||
public int OrderId { get; set; }
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,195 +1,159 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
|
||||
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 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);
|
||||
cart.ShoppingCartId = cart.GetCartId(context);
|
||||
return cart;
|
||||
_storeContext = storeContext;
|
||||
_cartId = cartId;
|
||||
}
|
||||
|
||||
// Helper method to simplify shopping cart calls
|
||||
public static ShoppingCart GetCart(MusicStoreEntities db, Controller controller)
|
||||
public static ShoppingCart GetCart(MusicStoreEntities storeContext, Controller controller)
|
||||
{
|
||||
return GetCart(db, controller.HttpContext);
|
||||
return new ShoppingCart(storeContext, GetCartId(controller.HttpContext));
|
||||
}
|
||||
|
||||
public void AddToCart(Album album)
|
||||
{
|
||||
// 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)
|
||||
private static string GetCartId(HttpContextBase context)
|
||||
{
|
||||
if (context.Session[CartSessionKey] == null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(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();
|
||||
var username = context.User.Identity.Name;
|
||||
|
||||
// Send tempCartId back to client as a cookie
|
||||
context.Session[CartSessionKey] = tempCartId.ToString();
|
||||
}
|
||||
context.Session[CartSessionKey] = !string.IsNullOrWhiteSpace(username)
|
||||
? username
|
||||
: Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
return context.Session[CartSessionKey].ToString();
|
||||
}
|
||||
|
||||
// When a user has logged in, migrate their shopping cart to
|
||||
// be associated with their username
|
||||
public void MigrateCart(string userName)
|
||||
public async Task AddToCart(Album album)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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" />
|
||||
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
|
||||
<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="MusicStoreEntities" connectionString="Data Source=(LocalDB)\v11.0; AttachDbFilename=|DataDirectory|\MvcMusicStore.mdf; 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;Initial Catalog=MusicStore;Integrated Security=True" providerName="System.Data.SqlClient" />
|
||||
</connectionStrings>
|
||||
<appSettings>
|
||||
<add key="DefaultAdminUsername" value="Administrator" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue