A few changes with this checkin:

1. Removing copyright text from all files per a code review feedback
2. Adding a cookie based session to the application to retrieve the cart Id.
3. Enabled the Accounts controller as we now have the necessary Http abstractions for User, SignIn, SignOut etc.
4. Changing self hosting scripts to run on coreclr by default.
5. Enabling the layout page on all required views.
6. Adding a favico.ico
7. Renaming the Cart property in the EF context to CartItems as it returns a CartItems list.
8. Uncommenting some code which was previously accessing unavailable APIs. They are available now (but yet to validate them).
This commit is contained in:
Praburaj 2014-04-02 18:40:25 -07:00
parent dabb68cc6d
commit 4709bca281
41 changed files with 595 additions and 659 deletions

View File

@ -11,5 +11,3 @@ rmdir /S /Q %APP_PATH%\Properties
del %APP_PATH%\*.csproj del %APP_PATH%\*.csproj
del %APP_PATH%\*.v12.suo del %APP_PATH%\*.v12.suo
del %APP_PATH%\*.csproj.user del %APP_PATH%\*.csproj.user
del src\PlaceHolder\*.csproj
rmdir /S /Q src\PlaceHolder\bin

View File

@ -2,10 +2,9 @@
### Run the application: ### Run the application:
1. Run build.cmd to restore all the necessary packages and generate project files 1. Run build.cmd to restore all the necessary packages and generate project files
2. Open a command prompt and cd \src\MusicStore\ 2. Open a command prompt and cd \src\<AppFolder>\
3. [Helios]: 3. [Helios]:
4. Execute CopyAspNetLoader.cmd to copy the AspNet.Loader.dll to the bin directory 4. Helios.cmd to launch the app on IISExpress.
5. Helios.cmd to launch the app on IISExpress.
4. [SelfHost]: 4. [SelfHost]:
5. Run Selfhost.cmd (This runs k web) (Note: If your changes to C# files are not picked up in successive builds - try deleting the bin and obj folder) 5. Run Selfhost.cmd (This runs k web) (Note: If your changes to C# files are not picked up in successive builds - try deleting the bin and obj folder)
5. [CustomHost]: 5. [CustomHost]:
@ -24,5 +23,5 @@
2. This is a captured snapshot of build numbers which worked for this application. This LKG will be captured once in a while. 2. This is a captured snapshot of build numbers which worked for this application. This LKG will be captured once in a while.
### Note: ### Note:
1. By default this script starts the application at http://localhost:5001/. Modify Run.cmd if you would like to change the url 1. By default the scripts will start the application at http://localhost:5001/. Modify the scripts to change the url.
2. Use Visual studio only for editing & intellisense. Don't try to build or run the app from Visual studio. 2. Use Visual studio only for editing & intellisense. Don't try to build or run the app from Visual studio.

View File

@ -1,505 +1,484 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Abstractions.Security;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.InMemory;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ModelBinding;
using MusicStore.Models;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
//using Microsoft.AspNet.Identity; namespace MusicStore.Controllers
//using Microsoft.AspNet.Identity.InMemory; {
//using Microsoft.AspNet.Mvc; //[Authorize]
//using Microsoft.AspNet.Mvc.ModelBinding; public class AccountController : Controller
//using MusicStore.Models; {
//using System; public AccountController()
//using System.Collections.Generic; //Bug: No EF yet - using an in memory store
//using System.Linq; //: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
//using System.Threading.Tasks; : this(new UserManager<ApplicationUser, string>(new InMemoryUserStore<ApplicationUser>()))
{
}
//namespace MusicStore.Controllers public AccountController(UserManager<ApplicationUser, string> userManager)
//{ {
// //[Authorize] UserManager = userManager;
// public class AccountController : Controller }
// {
// public AccountController()
// //Bug: No EF yet - using an in memory store
// //: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
// : this(new UserManager<ApplicationUser, string>(new InMemoryUserStore<ApplicationUser>()))
// {
// }
// public AccountController(UserManager<ApplicationUser, string> userManager) public UserManager<ApplicationUser, string> UserManager { get; private set; }
// {
// UserManager = userManager;
// }
// public UserManager<ApplicationUser, string> UserManager { get; private set; } //
// GET: /Account/Login
[AllowAnonymous]
public IActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
// private void MigrateShoppingCart(string UserName) //
// { // POST: /Account/Login
// //Bug: No EF //Bug: HTTP verb attribs not available
// //var storeDb = new MusicStoreEntities(); //[HttpPost]
// var storeDb = MusicStoreEntities.Instance; [AllowAnonymous]
//[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid == true)
{
var user = await UserManager.Find(model.UserName, model.Password);
if (user != null)
{
await SignIn(user, model.RememberMe);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// // Associate shopping cart items with logged-in user // If we got this far, something failed, redisplay form
// var cart = ShoppingCart.GetCart(storeDb, this.Context); return View(model);
// cart.MigrateCart(UserName); }
// storeDb.SaveChanges();
// //Bug: TODO //
// //Session[ShoppingCart.CartSessionKey] = UserName; // GET: /Account/Register
// } [AllowAnonymous]
public IActionResult Register()
{
return View();
}
// // //
// // GET: /Account/Login // POST: /Account/Register
// [AllowAnonymous] //Bug: Missing verb attributes
// public IActionResult Login(string returnUrl) //[HttpPost]
// { [AllowAnonymous]
// //ViewBag.ReturnUrl = returnUrl; //[ValidateAntiForgeryToken]
// return View(); public async Task<IActionResult> Register(RegisterViewModel model)
// } {
if (ModelState.IsValid == true)
{
var user = new ApplicationUser() { UserName = model.UserName };
var result = await UserManager.Create(user, model.Password);
if (result.Succeeded)
{
await SignIn(user, isPersistent: false);
//Bug: No helper methods
//return RedirectToAction("Index", "Home");
}
else
{
AddErrors(result);
}
}
// // // If we got this far, something failed, redisplay form
// // POST: /Account/Login return View(model);
// //Bug: HTTP verb attribs not available }
// //[HttpPost]
// [AllowAnonymous]
// //[ValidateAntiForgeryToken]
// public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
// {
// //Bug: How to validate the model state?
// //if (ModelState.IsValid)
// {
// var user = await UserManager.Find(model.UserName, model.Password);
// if (user != null)
// {
// await SignIn(user, model.RememberMe);
// return RedirectToLocal(returnUrl);
// }
// else
// {
// //Bug: Model state error
// //ModelState.AddModelError("", "Invalid username or password.");
// }
// }
// // If we got this far, something failed, redisplay form //
// return View(model); // POST: /Account/Disassociate
// } //Bug: HTTP verbs
//[HttpPost]
//[ValidateAntiForgeryToken]
public async Task<IActionResult> Disassociate(string loginProvider, string providerKey)
{
// // ManageMessageId? message = null;
// // GET: /Account/Register IdentityResult result = await UserManager.RemoveLogin(this.Context.User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
// [AllowAnonymous] if (result.Succeeded)
// public IActionResult Register() {
// { message = ManageMessageId.RemoveLoginSuccess;
// return View(); }
// } else
{
message = ManageMessageId.Error;
}
//Bug: No helpers available
//return RedirectToAction("Manage", new { Message = message });
return View();
}
// // //
// // POST: /Account/Register // GET: /Account/Manage
// //Bug: Missing verb attributes public IActionResult Manage(ManageMessageId? message)
// //[HttpPost] {
// [AllowAnonymous] ViewBag.StatusMessage =
// //[ValidateAntiForgeryToken] message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
// public async Task<IActionResult> Register(RegisterViewModel model) : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
// { : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
// //Bug: How to validate the model state? : message == ManageMessageId.Error ? "An error has occurred."
// //if (ModelState.IsValid) : "";
// { ViewBag.HasLocalPassword = HasPassword();
// //Bug: Replacing it with InmemoryUser //Bug: No Action method with single parameter
// var user = new ApplicationUser() { UserName = model.UserName }; //ViewBag.ReturnUrl = Url.Action("Manage");
// var result = await UserManager.Create(user, model.Password); //ViewBag.ReturnUrl = Url.Action("Manage", "Account", null);
// if (result.Succeeded) return View();
// { }
// await SignIn(user, isPersistent: false);
// //Bug: No helper methods
// //return RedirectToAction("Index", "Home");
// }
// else
// {
// AddErrors(result);
// }
// }
// // If we got this far, something failed, redisplay form //
// return View(model); // POST: /Account/Manage
// } //Bug: No verb attributes
//[HttpPost]
//[ValidateAntiForgeryToken]
public async Task<IActionResult> Manage(ManageUserViewModel model)
{
bool hasPassword = await HasPassword();
ViewBag.HasLocalPassword = hasPassword;
//Bug: No Action method with single parameter
//ViewBag.ReturnUrl = Url.Action("Manage");
//ViewBag.ReturnUrl = Url.Action("Manage", "Account", null);
if (hasPassword)
{
if (ModelState.IsValid == true)
{
IdentityResult result = await UserManager.ChangePassword(this.Context.User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
if (result.Succeeded)
{
//Bug: No helper method
//return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
return View();
}
else
{
AddErrors(result);
}
}
}
else
{
// User does not have a password so remove any validation errors caused by a missing OldPassword field
ModelState state = null;
ModelState.TryGetValue("OldPassword", out state);
// // if (state != null)
// // POST: /Account/Disassociate {
// //Bug: HTTP verbs state.Errors.Clear();
// //[HttpPost] }
// //[ValidateAntiForgeryToken]
// public async Task<IActionResult> Disassociate(string loginProvider, string providerKey)
// {
// ManageMessageId? message = null;
// IdentityResult result = await UserManager.RemoveLogin(User.Identity.GetUserId(), new UserLoginInfo(loginProvider, providerKey));
// if (result.Succeeded)
// {
// message = ManageMessageId.RemoveLoginSuccess;
// }
// else
// {
// message = ManageMessageId.Error;
// }
// //Bug: No helpers available
// //return RedirectToAction("Manage", new { Message = message });
// return View();
// }
// // if (ModelState.IsValid == true)
// // GET: /Account/Manage {
// public IActionResult Manage(ManageMessageId? message) IdentityResult result = await UserManager.AddPassword(this.Context.User.Identity.GetUserId(), model.NewPassword);
// { if (result.Succeeded)
// //ViewBag.StatusMessage = {
// // message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." //Bug: No helper method
// // : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." //return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
// // : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed." }
// // : message == ManageMessageId.Error ? "An error has occurred." else
// // : ""; {
// //ViewBag.HasLocalPassword = HasPassword(); AddErrors(result);
// //Bug: No Action method with single parameter }
// //ViewBag.ReturnUrl = Url.Action("Manage"); }
// //ViewBag.ReturnUrl = Url.Action("Manage", "Account", null); }
// return View();
// }
// // // If we got this far, something failed, redisplay form
// // POST: /Account/Manage return View(model);
// //Bug: No verb attributes }
// //[HttpPost]
// //[ValidateAntiForgeryToken]
// public async Task<IActionResult> Manage(ManageUserViewModel model)
// {
// bool hasPassword = await HasPassword();
// //ViewBag.HasLocalPassword = hasPassword;
// //Bug: No Action method with single parameter
// //ViewBag.ReturnUrl = Url.Action("Manage");
// //ViewBag.ReturnUrl = Url.Action("Manage", "Account", null);
// if (hasPassword)
// {
// //if (ModelState.IsValid)
// {
// IdentityResult result = await UserManager.ChangePassword(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
// if (result.Succeeded)
// {
// //Bug: No helper method
// //return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
// return View();
// }
// else
// {
// AddErrors(result);
// }
// }
// }
// else
// {
// // User does not have a password so remove any validation errors caused by a missing OldPassword field
// //Bug: Still controller does not have a ModelState property
// //ModelState state = ModelState["OldPassword"];
// ModelState state = null;
// if (state != null) //
// { // POST: /Account/ExternalLogin
// state.Errors.Clear(); //Bug: No verb attributes
// } //[HttpPost]
[AllowAnonymous]
//[ValidateAntiForgeryToken]
public IActionResult ExternalLogin(string provider, string returnUrl)
{
// Request a redirect to the external login provider
return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}
// //Bug: No model state validation //
// //if (ModelState.IsValid) // GET: /Account/ExternalLoginCallback
// { [AllowAnonymous]
// IdentityResult result = await UserManager.AddPassword(User.Identity.GetUserId(), model.NewPassword); public async Task<IActionResult> ExternalLoginCallback(string returnUrl)
// if (result.Succeeded) {
// { var loginInfo = await this.Context.Response.GetExternalLoginInfo();
// //Bug: No helper method if (loginInfo == null)
// //return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess }); {
// } //Bug: No helper
// else //return RedirectToAction("Login");
// { return View();
// AddErrors(result); }
// }
// }
// }
// // If we got this far, something failed, redisplay form // Sign in the user with this external login provider if the user already has a login
// return View(model); var user = await UserManager.Find(loginInfo.Login);
// } if (user != null)
{
await SignIn(user, isPersistent: 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 });
}
}
// // //
// // POST: /Account/ExternalLogin // POST: /Account/LinkLogin
// //Bug: No verb attributes //Bug: No HTTP verbs
// //[HttpPost] //[HttpPost]
// [AllowAnonymous] //[ValidateAntiForgeryToken]
// //[ValidateAntiForgeryToken] public IActionResult LinkLogin(string provider)
// public IActionResult ExternalLogin(string provider, string returnUrl) {
// { // Request a redirect to the external login provider to link a login for the current user
// // Request a redirect to the external login provider return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account", null), this.Context.User.Identity.GetUserId());
// return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl })); }
// }
// // //
// // GET: /Account/ExternalLoginCallback // GET: /Account/LinkLoginCallback
// [AllowAnonymous] public async Task<IActionResult> LinkLoginCallback()
// public async Task<IActionResult> ExternalLoginCallback(string returnUrl) {
// { var loginInfo = await this.Context.Response.GetExternalLoginInfo(XsrfKey, this.Context.User.Identity.GetUserId());
// var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync(); if (loginInfo == null)
// if (loginInfo == null) {
// { //Bug: No helper method
// //Bug: No helper //return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
// //return RedirectToAction("Login"); return View();
// return View(); }
// } var result = await UserManager.AddLogin(this.Context.User.Identity.GetUserId(), loginInfo.Login);
if (result.Succeeded)
{
//Bug: No helper method
//return RedirectToAction("Manage");
return View();
}
//Bug: No helper method
//return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
return View();
}
// // Sign in the user with this external login provider if the user already has a login //
// var user = await UserManager.Find(loginInfo.Login); // POST: /Account/ExternalLoginConfirmation
// if (user != null) //Bug: No HTTP verbs
// { //[HttpPost]
// await SignIn(user, isPersistent: false); [AllowAnonymous]
// return RedirectToLocal(returnUrl); //[ValidateAntiForgeryToken]
// } public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
// else {
// { if (this.Context.User.Identity.IsAuthenticated)
// // If the user does not have an account, then prompt the user to create an account {
// //ViewBag.ReturnUrl = returnUrl; //Bug: No helper yet
// //ViewBag.LoginProvider = loginInfo.Login.LoginProvider; //return RedirectToAction("Manage");
// return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { UserName = loginInfo.DefaultUserName }); return View();
// } }
// }
// // if (ModelState.IsValid == true)
// // POST: /Account/LinkLogin {
// //Bug: No HTTP verbs // Get the information about the user from the external login provider
// //[HttpPost] var info = await this.Context.Response.GetExternalLoginInfo();
// //[ValidateAntiForgeryToken] if (info == null)
// public IActionResult LinkLogin(string provider) {
// { return View("ExternalLoginFailure");
// // Request a redirect to the external login provider to link a login for the current user }
// return new ChallengeResult(provider, Url.Action("LinkLoginCallback", "Account", null), User.Identity.GetUserId());
// }
// // var user = new ApplicationUser() { UserName = model.UserName };
// // GET: /Account/LinkLoginCallback var result = await UserManager.Create(user);
// public async Task<IActionResult> LinkLoginCallback() if (result.Succeeded)
// { {
// var loginInfo = null;// await AuthenticationManager.GetExternalLoginInfoAsync(XsrfKey, User.Identity.GetUserId()); result = await UserManager.AddLogin(user.Id, info.Login);
// if (loginInfo == null) if (result.Succeeded)
// { {
// //Bug: No helper method await SignIn(user, isPersistent: false);
// //return RedirectToAction("Manage", new { Message = ManageMessageId.Error }); return RedirectToLocal(returnUrl);
// return View(); }
// } }
// var result = await UserManager.AddLogin(User.Identity.GetUserId(), loginInfo.Login); AddErrors(result);
// if (result.Succeeded) }
// {
// //Bug: No helper method
// //return RedirectToAction("Manage");
// return View();
// }
// //Bug: No helper method
// //return RedirectToAction("Manage", new { Message = ManageMessageId.Error });
// return View();
// }
// // ViewBag.ReturnUrl = returnUrl;
// // POST: /Account/ExternalLoginConfirmation return View(model);
// //Bug: No HTTP verbs }
// //[HttpPost]
// [AllowAnonymous]
// //[ValidateAntiForgeryToken]
// public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
// {
// if (User.Identity.IsAuthenticated)
// {
// //Bug: No helper yet
// //return RedirectToAction("Manage");
// return View();
// }
// //Bug: No model state validation //
// //if (ModelState.IsValid) // POST: /Account/LogOff
// { //Bug: No HTTP verbs
// // Get the information about the user from the external login provider //[HttpPost]
// var info = await AuthenticationManager.GetExternalLoginInfoAsync(); //[ValidateAntiForgeryToken]
// if (info == null) public IActionResult LogOff()
// { {
// return View("ExternalLoginFailure"); this.Context.Response.SignOut();
// } //Bug: No helper
// //Using InMemory user //return RedirectToAction("Index", "Home");
// var user = new ApplicationUser() { UserName = model.UserName }; return View();
// var result = await UserManager.Create(user); }
// if (result.Succeeded)
// {
// result = await UserManager.AddLogin(user.Id, info.Login);
// if (result.Succeeded)
// {
// await SignIn(user, isPersistent: false);
// return RedirectToLocal(returnUrl);
// }
// }
// AddErrors(result);
// }
// //ViewBag.ReturnUrl = returnUrl; //
// return View(model); // GET: /Account/ExternalLoginFailure
// } [AllowAnonymous]
public IActionResult ExternalLoginFailure()
{
return View();
}
// // //Bug: Need this attribute
// // POST: /Account/LogOff //[ChildActionOnly]
// //Bug: No HTTP verbs public async Task<IActionResult> RemoveAccountList()
// //[HttpPost] {
// //[ValidateAntiForgeryToken] var linkedAccounts = await UserManager.GetLogins(this.Context.User.Identity.GetUserId());
// public IActionResult LogOff() ViewBag.ShowRemoveButton = await HasPassword() || linkedAccounts.Count > 1;
// { //Bug: We dont have partial views yet
// AuthenticationManager.SignOut(); //return (IActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
// //return RedirectToAction("Index", "Home"); return View();
// return View(); }
// }
// // //Bug: Controllers need to be disposable?
// // GET: /Account/ExternalLoginFailure protected void Dispose(bool disposing)
// [AllowAnonymous] {
// public IActionResult ExternalLoginFailure() if (disposing && UserManager != null)
// { {
// return View(); UserManager.Dispose();
// } UserManager = null;
}
// //Bug: Need this attribute //base.Dispose(disposing);
// //[ChildActionOnly] }
// public async Task<IActionResult> RemoveAccountList()
// {
// var linkedAccounts = await UserManager.GetLogins(User.Identity.GetUserId());
// //ViewBag.ShowRemoveButton = await HasPassword() || linkedAccounts.Count > 1;
// //Bug: We dont have partial views yet
// //return (IActionResult)PartialView("_RemoveAccountPartial", linkedAccounts);
// return View();
// }
// //Bug: Controllers need to be disposable? #region Helpers
// protected void Dispose(bool disposing) // Used for XSRF protection when adding external logins
// { private const string XsrfKey = "XsrfId";
// if (disposing && UserManager != null)
// {
// UserManager.Dispose();
// UserManager = null;
// }
// //base.Dispose(disposing);
// }
// #region Helpers private async Task SignIn(ApplicationUser user, bool isPersistent)
// // Used for XSRF protection when adding external logins {
// private const string XsrfKey = "XsrfId"; this.Context.Response.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
this.Context.Response.SignIn(identity, new AuthenticationProperties() { IsPersistent = isPersistent });
}
// //private IAuthenticationManager AuthenticationManager private void AddErrors(IdentityResult result)
// //{ {
// // get foreach (var error in result.Errors)
// // { {
// // //Will change to Context.Authentication ModelState.AddModelError("", error);
// // return new IAuthenticationManager(); }
// // } }
// //}
// private async Task SignIn(ApplicationUser user, bool isPersistent) private async Task<bool> HasPassword()
// { {
// //Bug: No cookies middleware now. var user = await UserManager.FindById(this.Context.User.Identity.GetUserId());
// //AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); if (user != null)
// //var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); {
// //AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity); return user.PasswordHash != null;
}
return false;
}
// // Migrate the user's shopping cart public enum ManageMessageId
// MigrateShoppingCart(user.UserName); {
// } ChangePasswordSuccess,
SetPasswordSuccess,
RemoveLoginSuccess,
Error
}
// private void AddErrors(IdentityResult result) private IActionResult RedirectToLocal(string returnUrl)
// { {
// foreach (var error in result.Errors) //Bug: No helpers available
// { //if (Url.IsLocalUrl(returnUrl))
// //ModelState.AddModelError("", error); //{
// } // return Redirect(returnUrl);
// } //}
//else
//{
// return RedirectToAction("Index", "Home");
//}
return View();
}
// private async Task<bool> HasPassword() private class ChallengeResult : HttpStatusCodeResult
// { {
// //Bug: Need to get the User object somehow: TODO public ChallengeResult(string provider, string redirectUri)
// //var user = await UserManager.FindById(User.Identity.GetUserId()); : this(provider, redirectUri, null)
// var user = await UserManager.FindById("TODO"); {
// if (user != null) }
// {
// return user.PasswordHash != null;
// }
// return false;
// }
// public enum ManageMessageId public ChallengeResult(string provider, string redirectUri, string userId)
// { : base(401)
// ChangePasswordSuccess, {
// SetPasswordSuccess, LoginProvider = provider;
// RemoveLoginSuccess, RedirectUri = redirectUri;
// Error UserId = userId;
// } }
// private IActionResult RedirectToLocal(string returnUrl) public string LoginProvider { get; set; }
// { public string RedirectUri { get; set; }
// //Bug: No helpers available public string UserId { get; set; }
// //if (Url.IsLocalUrl(returnUrl))
// //{
// // return Redirect(returnUrl);
// //}
// //else
// //{
// // return RedirectToAction("Index", "Home");
// //}
// return View();
// }
// private class ChallengeResult : HttpStatusCodeResult new public void ExecuteResultAsync(ActionContext context)
// { {
// public ChallengeResult(string provider, string redirectUri) var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
// : this(provider, redirectUri, null) if (UserId != null)
// { {
// } properties.Dictionary[XsrfKey] = UserId;
}
// public ChallengeResult(string provider, string redirectUri, string userId) context.HttpContext.Response.Challenge(LoginProvider, properties);
// : base(401) }
// { }
// LoginProvider = provider; #endregion
// RedirectUri = redirectUri; }
// UserId = userId;
// }
// public string LoginProvider { get; set; } /// <summary>
// public string RedirectUri { get; set; } /// TODO: Temporary APIs to unblock build. Need to remove this once we have these APIs available.
// public string UserId { get; set; } /// </summary>
public static class Extensions
{
public static string GetUserId(this IIdentity user)
{
return string.Empty;
}
// new public void ExecuteResultAsync(ActionContext context) public static Task<ExternalLoginInfo> GetExternalLoginInfo(this HttpResponse response)
// { {
// //Bug: No security package yet return Task.FromResult<ExternalLoginInfo>(new ExternalLoginInfo());
// //var properties = new AuthenticationProperties() { RedirectUri = RedirectUri }; }
// //if (UserId != null)
// //{
// // properties.Dictionary[XsrfKey] = UserId;
// //}
// //context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
// }
// }
// #endregion
// }
// //Bug: To remove this. Until we have ClaimsPrincipal available public static Task<ExternalLoginInfo> GetExternalLoginInfo(this HttpResponse response, string xsrfKey, string expectedValue)
// internal class User {
// { return Task.FromResult<ExternalLoginInfo>(new ExternalLoginInfo());
// public static IdentityInstance Identity { get; set; } }
}
// public User() /// <summary>
// { /// TODO: Temporary APIs to unblock build. Need to remove this once we have these APIs available.
// if (Identity == null) /// </summary>
// { public class ExternalLoginInfo
// Identity = new IdentityInstance(); {
// } public string DefaultUserName { get; set; }
// } public UserLoginInfo Login { get; set; }
}
// internal class IdentityInstance /// <summary>
// { /// TODO: Temporary APIs to unblock build. Need to remove this once we have these APIs available.
// public string GetUserId() /// </summary>
// { public static class DefaultAuthenticationTypes
// return string.Empty; {
// } public const string ApplicationCookie = "Application";
public const string ExternalCookie = "External";
// public bool IsAuthenticated { get; set; } }
// } }
// }
//}

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc;
using MusicStore.Models; using MusicStore.Models;
using System; using System;
using System.Linq; using System.Linq;
@ -26,20 +24,16 @@ namespace MusicStore.Controllers
// //
// POST: /Checkout/AddressAndPayment // POST: /Checkout/AddressAndPayment
//Bug: Http verbs not available. Also binding to FormCollection is not available. //Bug: Http verbs not available.
//Bug: Using direct model binding until we have TryUpdateModel available.
//[HttpPost] //[HttpPost]
//public IActionResult AddressAndPayment(FormCollection values) //public IActionResult AddressAndPayment(FormCollection values)
public async Task<IActionResult> AddressAndPayment(int workaroundId) public async Task<IActionResult> AddressAndPayment(Order order)
{ {
var formCollection = await Context.Request.GetFormAsync(); var formCollection = await Context.Request.GetFormAsync();
var order = new Order();
//TryUpdateModel(order);
try try
{ {
//if (string.Equals(values["PromoCode"], PromoCode,
// StringComparison.OrdinalIgnoreCase) == false)
if (string.Equals(formCollection.GetValues("PromoCode").FirstOrDefault(), PromoCode, if (string.Equals(formCollection.GetValues("PromoCode").FirstOrDefault(), PromoCode,
StringComparison.OrdinalIgnoreCase) == false) StringComparison.OrdinalIgnoreCase) == false)
{ {
@ -52,20 +46,9 @@ namespace MusicStore.Controllers
? db.Orders.Max(o => o.OrderId) + 1 ? db.Orders.Max(o => o.OrderId) + 1
: 1; : 1;
//Bug: Object values should come from page (putting in hard coded values as EF can't work with nulls against SQL Server yet)
//Bug: Identity not available
order.Username = "unknown"; //User.Identity.Name;
order.OrderId = nextId; order.OrderId = nextId;
order.Username = this.Context.User.Identity.Name;
order.OrderDate = DateTime.Now; order.OrderDate = DateTime.Now;
order.FirstName = "John";
order.LastName = "Doe";
order.Address = "One Microsoft Way";
order.City = "Redmond";
order.State = "WA";
order.Country = "USA";
order.Email = "john.doe@example.com";
order.Phone = "555-555-5555";
order.PostalCode = "98052";
//Add the Order //Add the Order
db.Orders.Add(order); db.Orders.Add(order);
@ -82,7 +65,6 @@ namespace MusicStore.Controllers
// new { id = order.OrderId }); // new { id = order.OrderId });
return View(); return View();
} }
} }
catch catch
{ {
@ -97,13 +79,9 @@ namespace MusicStore.Controllers
public IActionResult Complete(int id) public IActionResult Complete(int id)
{ {
// Validate customer owns this order // Validate customer owns this order
//Bug: Identity not available
//bool isValid = storeDB.Orders.Any(
// o => o.OrderId == id &&
// o.Username == User.Identity.Name);
bool isValid = db.Orders.Any( bool isValid = db.Orders.Any(
o => o.OrderId == id); o => o.OrderId == id &&
o.Username == this.Context.User.Identity.Name);
if (isValid) if (isValid)
{ {

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc;
using MusicStore.Models; using MusicStore.Models;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc;
using MusicStore.Models; using MusicStore.Models;
using MusicStore.ViewModels; using MusicStore.ViewModels;
using System.Linq; using System.Linq;
@ -64,7 +62,7 @@ namespace MusicStore.Controllers
// Get the name of the album to display confirmation // Get the name of the album to display confirmation
// TODO [EF] Turn into one query once query of related data is enabled // TODO [EF] Turn into one query once query of related data is enabled
int albumId = db.Carts.Single(item => item.CartItemId == id).AlbumId; int albumId = db.CartItems.Single(item => item.CartItemId == id).AlbumId;
string albumName = db.Albums.Single(a => a.AlbumId == albumId).Title; string albumName = db.Albums.Single(a => a.AlbumId == albumId).Title;
// Remove from cart // Remove from cart

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc;
using MusicStore.Models; using MusicStore.Models;
using System.Linq; using System.Linq;

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.Data.Entity; using Microsoft.Data.Entity;
using MusicStore.Models; using MusicStore.Models;
@ -49,32 +47,31 @@ namespace MusicStore.Controllers
// //
// GET: /StoreManager/Create // GET: /StoreManager/Create
//public IActionResult Create() public IActionResult Create()
//{ {
// ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name"); //ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");
// ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name"); //ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
// return View(); return View();
//} }
//Bug: ModelState.IsValid not available
//Bug: RedirectToAction() not available
//Bug: SelectList not available //Bug: SelectList not available
// POST: /StoreManager/Create // POST: /StoreManager/Create
//[HttpPost] //[HttpPost]
//public IActionResult Create(Album album) public IActionResult Create(Album album)
//{ {
// if (ModelState.IsValid) if (ModelState.IsValid == true)
// { {
// db.Albums.Add(album); db.Albums.Add(album);
// db.SaveChanges(); db.SaveChanges();
// return RedirectToAction("Index"); //Bug: RedirectToAction() not available
// } //return RedirectToAction("Index");
return View();
}
// ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId); //ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
// ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId); //ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);
// return View(album); return View(album);
//} }
// //
// GET: /StoreManager/Edit/5 // GET: /StoreManager/Edit/5
@ -100,13 +97,13 @@ namespace MusicStore.Controllers
//[HttpPost] //[HttpPost]
public IActionResult Edit(Album album) public IActionResult Edit(Album album)
{ {
//Bug: ModelState.IsValid missing if (ModelState.IsValid == true)
//if (ModelState.IsValid)
{ {
db.ChangeTracker.Entry(album).State = EntityState.Modified; db.ChangeTracker.Entry(album).State = EntityState.Modified;
db.SaveChanges(); db.SaveChanges();
//Bug: Missing RedirectToAction helper //Bug: Missing RedirectToAction helper
//return RedirectToAction("Index"); //return RedirectToAction("Index");
return View();
} }
//ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId); //ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId);
//ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId); //ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId);

View File

@ -1,3 +1,6 @@
REM run on k10 by default. Assign it to an empty value to run on desktop CLR.
SET TARGET_FRAMEWORK=k10
REM Selfhost does not need this bin folder REM Selfhost does not need this bin folder
rmdir /S /Q bin rmdir /S /Q bin

View File

@ -1 +1,4 @@
REM copy the AspNet.Loader.dll to the bin folder
call CopyAspNetLoader.cmd
"%ProgramFiles(x86)%\iis Express\iisexpress.exe" /port:5001 /path:"%cd%" "%ProgramFiles(x86)%\iis Express\iisexpress.exe" /port:5001 /path:"%cd%"

View File

@ -1,31 +1,32 @@
{ {
"version": "0.1-alpha-*", "version": "0.1-alpha-*",
"dependencies": { "dependencies": {
"Helios": "0.1-alpha-107", "Helios": "0.1-alpha-168",
"Microsoft.AspNet.Abstractions": "0.1-alpha-162", "Microsoft.AspNet.Abstractions": "0.1-alpha-210",
"Microsoft.AspNet.Mvc": "0.1-alpha-324", "Microsoft.AspNet.Mvc": "0.1-alpha-449",
"Microsoft.AspNet.Razor": "0.1-alpha-144", "Microsoft.AspNet.Razor": "0.1-alpha-181",
"Microsoft.AspNet.ConfigurationModel": "0.1-alpha-117", "Microsoft.AspNet.ConfigurationModel": "0.1-alpha-167",
"Microsoft.AspNet.DependencyInjection": "0.1-alpha-169", "Microsoft.AspNet.DependencyInjection": "0.1-alpha-232",
"Microsoft.AspNet.RequestContainer": "0.1-alpha-133", "Microsoft.AspNet.RequestContainer": "0.1-alpha-201",
"Microsoft.AspNet.Routing": "0.1-alpha-115", "Microsoft.AspNet.Routing": "0.1-alpha-182",
"Microsoft.AspNet.Mvc.ModelBinding": "0.1-alpha-324", "Microsoft.AspNet.Mvc.ModelBinding": "0.1-alpha-449",
"Microsoft.AspNet.Mvc.Core": "0.1-alpha-324", "Microsoft.AspNet.Mvc.Core": "0.1-alpha-449",
"Microsoft.AspNet.Mvc.Razor": "0.1-alpha-324", "Microsoft.AspNet.Mvc.Razor": "0.1-alpha-449",
"Microsoft.AspNet.Mvc.Rendering": "0.1-alpha-324", "Microsoft.AspNet.Mvc.Rendering": "0.1-alpha-449",
"Microsoft.AspNet.StaticFiles": "0.1-alpha-090", "Microsoft.AspNet.StaticFiles": "0.1-alpha-146",
"System.Security.Claims": "0.1-alpha-052", "System.Security.Claims": "0.1-alpha-094",
"Microsoft.AspNet.Security.DataProtection": "0.1-alpha-100", "System.Security.Principal": "4.0.0.0",
"Microsoft.AspNet.Identity": "0.1-alpha-164", "Microsoft.AspNet.Security.DataProtection": "0.1-alpha-141",
"Microsoft.AspNet.Identity.Entity": "0.1-alpha-164", "Microsoft.AspNet.Identity": "0.1-alpha-238",
"Microsoft.AspNet.Identity.InMemory": "0.1-alpha-164", "Microsoft.AspNet.Identity.Entity": "0.1-alpha-238",
"Microsoft.Data.Entity": "0.1-alpha-284", "Microsoft.AspNet.Identity.InMemory": "0.1-alpha-238",
"Microsoft.Data.Relational": "0.1-alpha-284", "Microsoft.Data.Entity": "0.1-alpha-380",
"Microsoft.Data.SqlServer": "0.1-pre-284", "Microsoft.Data.Relational": "0.1-alpha-380",
"Microsoft.Data.InMemory": "0.1-alpha-284", "Microsoft.Data.SqlServer": "0.1-pre-380",
"Microsoft.AspNet.Diagnostics": "0.1-alpha-025", "Microsoft.Data.InMemory": "0.1-alpha-380",
"Microsoft.AspNet.Hosting": "0.1-alpha-133", "Microsoft.AspNet.Diagnostics": "0.1-alpha-081",
"Microsoft.AspNet.Server.WebListener": "0.1-alpha-039" "Microsoft.AspNet.Hosting": "0.1-alpha-201",
"Microsoft.AspNet.Server.WebListener": "0.1-alpha-105"
}, },
"configurations": { "configurations": {
"net45": { "net45": {
@ -41,7 +42,7 @@
"System.Linq": "4.0.0.0", "System.Linq": "4.0.0.0",
"System.Runtime": "4.0.20.0", "System.Runtime": "4.0.20.0",
"System.Dynamic.Runtime": "4.0.0.0", "System.Dynamic.Runtime": "4.0.0.0",
"System.Threading.Tasks": "4.0.0.0", "System.Threading.Tasks": "4.0.10.0",
"System.ComponentModel": "4.0.0.0", "System.ComponentModel": "4.0.0.0",
"System.Console": "4.0.0.0", "System.Console": "4.0.0.0",
"System.Diagnostics.Debug": "4.0.10.0", "System.Diagnostics.Debug": "4.0.10.0",

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace MusicStore.Models namespace MusicStore.Models
{ {

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace MusicStore.Models namespace MusicStore.Models

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace MusicStore.Models namespace MusicStore.Models
{ {

View File

@ -1,12 +1,11 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System;
using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace MusicStore.Models namespace MusicStore.Models
{ {
public class CartItem public class CartItem
{ {
[Key]
public int CartItemId { get; set; } public int CartItemId { get; set; }
[Required] [Required]

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace MusicStore.Models namespace MusicStore.Models

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet.Identity.InMemory;
using Microsoft.AspNet.Identity.InMemory;
namespace MusicStore.Models namespace MusicStore.Models
{ {

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.Data.Entity;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Metadata; using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.InMemory; using Microsoft.Data.InMemory;
using Microsoft.Data.SqlServer; using Microsoft.Data.SqlServer;
@ -13,7 +11,7 @@ namespace MusicStore.Models
public EntitySet<Artist> Artists { get; set; } public EntitySet<Artist> Artists { get; set; }
public EntitySet<Order> Orders { get; set; } public EntitySet<Order> Orders { get; set; }
public EntitySet<Genre> Genres { get; set; } public EntitySet<Genre> Genres { get; set; }
public EntitySet<CartItem> Carts { get; set; } public EntitySet<CartItem> CartItems { get; set; }
public EntitySet<OrderDetail> OrderDetails { get; set; } public EntitySet<OrderDetail> OrderDetails { get; set; }
protected override void OnConfiguring(EntityConfigurationBuilder builder) protected override void OnConfiguring(EntityConfigurationBuilder builder)

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace MusicStore.Models namespace MusicStore.Models

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. namespace MusicStore.Models
namespace MusicStore.Models
{ {
public class OrderDetail public class OrderDetail
{ {

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.Data.Entity;
using Microsoft.Data.Entity;
using Microsoft.Data.SqlServer; using Microsoft.Data.SqlServer;
using MusicStore.Models; using MusicStore.Models;
using System; using System;

View File

@ -1,7 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity; using Microsoft.Data.Entity;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -19,8 +16,6 @@ namespace MusicStore.Models
_db = db; _db = db;
} }
public const string CartSessionKey = "CartId";
public static ShoppingCart GetCart(MusicStoreContext db, HttpContext context) public static ShoppingCart GetCart(MusicStoreContext db, HttpContext context)
{ {
var cart = new ShoppingCart(db); var cart = new ShoppingCart(db);
@ -38,15 +33,15 @@ namespace MusicStore.Models
public void AddToCart(Album album) public void AddToCart(Album album)
{ {
// Get the matching cart and album instances // Get the matching cart and album instances
var cartItem = _db.Carts.SingleOrDefault( var cartItem = _db.CartItems.SingleOrDefault(
c => c.CartId == ShoppingCartId c => c.CartId == ShoppingCartId
&& c.AlbumId == album.AlbumId); && c.AlbumId == album.AlbumId);
if (cartItem == null) if (cartItem == null)
{ {
// TODO [EF] Swap to store generated key once we support identity pattern // TODO [EF] Swap to store generated key once we support identity pattern
var nextCartItemId = _db.Carts.Any() var nextCartItemId = _db.CartItems.Any()
? _db.Carts.Max(c => c.CartItemId) + 1 ? _db.CartItems.Max(c => c.CartItemId) + 1
: 1; : 1;
// Create a new cart item if no cart item exists // Create a new cart item if no cart item exists
@ -59,7 +54,7 @@ namespace MusicStore.Models
DateCreated = DateTime.Now DateCreated = DateTime.Now
}; };
_db.Carts.Add(cartItem); _db.CartItems.Add(cartItem);
} }
else else
{ {
@ -67,14 +62,14 @@ namespace MusicStore.Models
cartItem.Count++; cartItem.Count++;
// TODO [EF] Remove this line once change detection is available // TODO [EF] Remove this line once change detection is available
_db.ChangeTracker.Entry(cartItem).State = Microsoft.Data.Entity.EntityState.Modified; _db.ChangeTracker.Entry(cartItem).State = EntityState.Modified;
} }
} }
public int RemoveFromCart(int id) public int RemoveFromCart(int id)
{ {
// Get the cart // Get the cart
var cartItem = _db.Carts.Single( var cartItem = _db.CartItems.Single(
cart => cart.CartId == ShoppingCartId cart => cart.CartId == ShoppingCartId
&& cart.CartItemId == id); && cart.CartItemId == id);
@ -93,7 +88,7 @@ namespace MusicStore.Models
} }
else else
{ {
_db.Carts.Remove(cartItem); _db.CartItems.Remove(cartItem);
} }
} }
@ -103,7 +98,7 @@ namespace MusicStore.Models
public void EmptyCart() public void EmptyCart()
{ {
var cartItems = _db.Carts.Where(cart => cart.CartId == ShoppingCartId); var cartItems = _db.CartItems.Where(cart => cart.CartId == ShoppingCartId);
foreach (var cartItem in cartItems) foreach (var cartItem in cartItems)
{ {
@ -115,13 +110,13 @@ namespace MusicStore.Models
public List<CartItem> GetCartItems() public List<CartItem> GetCartItems()
{ {
return _db.Carts.Where(cart => cart.CartId == ShoppingCartId).ToList(); return _db.CartItems.Where(cart => cart.CartId == ShoppingCartId).ToList();
} }
public int GetCount() public int GetCount()
{ {
// Get the count of each item in the cart and sum them up // Get the count of each item in the cart and sum them up
int? count = (from cartItems in _db.Carts int? count = (from cartItems in _db.CartItems
where cartItems.CartId == ShoppingCartId where cartItems.CartId == ShoppingCartId
select (int?)cartItems.Count).Sum(); select (int?)cartItems.Count).Sum();
@ -137,7 +132,7 @@ namespace MusicStore.Models
// TODO Collapse to a single query once EF supports querying related data // TODO Collapse to a single query once EF supports querying related data
decimal total = 0; decimal total = 0;
foreach (var item in _db.Carts.Where(c => c.CartId == ShoppingCartId)) foreach (var item in _db.CartItems.Where(c => c.CartId == ShoppingCartId))
{ {
var album = _db.Albums.Single(a => a.AlbumId == item.AlbumId); var album = _db.Albums.Single(a => a.AlbumId == item.AlbumId);
total += item.Count * album.Price; total += item.Count * album.Price;
@ -194,38 +189,23 @@ namespace MusicStore.Models
// We're using HttpContextBase to allow access to cookies. // We're using HttpContextBase to allow access to cookies.
public string GetCartId(HttpContext context) public string GetCartId(HttpContext context)
{ {
//Bug: Session not in scope. But we should substitute this with cookies when available. var sessionCookie = context.Request.Cookies.Get("Session");
//if (context.Session[CartSessionKey] == null) string cartId = 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();
// // Send tempCartId back to client as a cookie if (string.IsNullOrWhiteSpace(sessionCookie))
// context.Session[CartSessionKey] = tempCartId.ToString();
// }
//}
//return context.Session[CartSessionKey].ToString();
return string.Empty;
}
// When a user has logged in, migrate their shopping cart to
// be associated with their username
public void MigrateCart(string userName)
{
var shoppingCart = _db.Carts.Where(c => c.CartId == ShoppingCartId);
foreach (CartItem item in shoppingCart)
{ {
item.CartId = userName; //A GUID to hold the cartId.
cartId = Guid.NewGuid().ToString();
// Send cart Id as a cookie to the client.
context.Response.Cookies.Append("Session", cartId);
}
else
{
cartId = sessionCookie;
} }
return cartId;
} }
} }
} }

View File

@ -1 +0,0 @@
"%ProgramFiles(x86)%\iis Express\iisexpress.exe" /port:5001 /path:"%cd%"

View File

@ -1,3 +1,6 @@
REM run on k10 by default. Assign it to an empty value to run on desktop CLR.
SET TARGET_FRAMEWORK=k10
REM Selfhost does not need this bin folder REM Selfhost does not need this bin folder
rmdir /S /Q bin rmdir /S /Q bin

View File

@ -1,11 +1,10 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using Microsoft.AspNet;
using Microsoft.AspNet;
using Microsoft.AspNet.Abstractions; using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.ConfigurationModel; using Microsoft.AspNet.ConfigurationModel;
using Microsoft.AspNet.DependencyInjection; using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.DependencyInjection.Fallback; using Microsoft.AspNet.DependencyInjection.Fallback;
using Microsoft.AspNet.DependencyInjection.NestedProviders; using Microsoft.AspNet.DependencyInjection.NestedProviders;
using Microsoft.AspNet.RequestContainer;
using Microsoft.AspNet.Diagnostics; using Microsoft.AspNet.Diagnostics;
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.InMemory; using Microsoft.AspNet.Identity.InMemory;
@ -22,11 +21,13 @@ public class Startup
{ {
CreateAdminUser(); CreateAdminUser();
//ErrorPageOptions.ShowAll to be used only at development time. Not recommended for production.
app.UseErrorPage(ErrorPageOptions.ShowAll); app.UseErrorPage(ErrorPageOptions.ShowAll);
app.UseFileServer(); app.UseFileServer();
var serviceProvider = MvcServices.GetDefaultServices().BuildServiceProvider(app.ServiceProvider); var serviceProvider = MvcServices.GetDefaultServices().BuildServiceProvider(app.ServiceProvider);
app.UseContainer(serviceProvider);
var routes = new RouteCollection() var routes = new RouteCollection()
{ {

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. namespace MusicStore.ViewModels
namespace MusicStore.ViewModels
{ {
public class ShoppingCartRemoveViewModel public class ShoppingCartRemoveViewModel
{ {

View File

@ -1,6 +1,4 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic;
using System.Collections.Generic;
using MusicStore.Models; using MusicStore.Models;
namespace MusicStore.ViewModels namespace MusicStore.ViewModels

View File

@ -1,6 +1,5 @@
@*Bug: Having a ViewBag.Title throws compilation error: https://github.com/aspnet/WebFx/issues/67*@ @{
@{ Layout = "/Views/Shared/_Layout.cshtml";
//Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Home Page"; ViewBag.Title = "Home Page";
} }

View File

@ -41,7 +41,8 @@
<hr /> <hr />
<footer class="navbar navbar-fixed-bottom navbar-default text-center"> <footer class="navbar navbar-fixed-bottom navbar-default text-center">
<p><a href="http://mvcmusicstore.codeplex.com">mvcmusicstore.codeplex.com</a></p> <p><a href="http://mvcmusicstore.codeplex.com">mvcmusicstore.codeplex.com</a></p>
<small>@Html.ActionLink("admin", "Index", "StoreManager")</small> @*Bug: No Html helpers yet*@
@*<small>@Html.ActionLink("admin", "Index", "StoreManager")</small>*@
</footer> </footer>
</div> </div>
@ -54,4 +55,4 @@
<script src="/Scripts/bootstrap.js"></script> <script src="/Scripts/bootstrap.js"></script>
<script src="/Scripts/respond.js"></script> <script src="/Scripts/respond.js"></script>
</body> </body>
</html> </html>

View File

@ -1,4 +1,9 @@
@if (ViewBag.CartCount > 0) @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
}
@if (ViewBag.CartCount > 0)
{ {
<li> <li>
<a href="@Url.Action("Index", "ShoppingCart")" title="@ViewBag.CartSummary"> <a href="@Url.Action("Index", "ShoppingCart")" title="@ViewBag.CartSummary">

View File

@ -1,9 +1,11 @@
@model MvcMusicStore.ViewModels.ShoppingCartViewModel @model MusicStore.ViewModels.ShoppingCartViewModel
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Shopping Cart"; ViewBag.Title = "Shopping Cart";
} }
@section Scripts { @*//@section Scripts {*@
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
// Document.ready -> link up remove event handler // Document.ready -> link up remove event handler
@ -33,13 +35,13 @@
}); });
</script> </script>
} @*}*@
<h3> <h3>
<em>Review</em> your cart: <em>Review</em> your cart:
</h3> </h3>
<p class="button"> <p class="button">
@Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout") @*@Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")*@
</p> </p>
<div id="update-message"> <div id="update-message">
</div> </div>
@ -58,22 +60,22 @@
</tr> </tr>
@foreach (var item in Model.CartItems) @foreach (var item in Model.CartItems)
{ {
<tr id="row-@item.RecordId"> <tr id="row-@item.CartItemId">
<td> <td>
@Html.ActionLink(item.Album.Title, @*@Html.ActionLink(item.Album.Title,
"Details", "Store", new { id = item.AlbumId }, null) "Details", "Store", new { id = item.AlbumId }, null)*@
</td> </td>
<td> <td>
@item.Album.Price @item.Album.Price
</td> </td>
<td id="item-count-@item.RecordId"> <td id="item-count-@item.CartItemId">
@item.Count @item.Count
</td> </td>
<td> <td>
<a href="#" class="RemoveLink" data-id="@item.RecordId" @*<a href="#" class="RemoveLink" data-id="@item.RecordId"
data-url='@Url.Content("~/ShoppingCart/RemoveFromCart")'> data-url='@Url.Content("~/ShoppingCart/RemoveFromCart")'>
Remove from cart Remove from cart
</a> </a>*@
</td> </td>
</tr> </tr>
} }

View File

@ -1,5 +1,7 @@
@model MusicStore.Models.Genre @model MusicStore.Models.Genre
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Browse Albums"; ViewBag.Title = "Browse Albums";
} }
<div class="genre"> <div class="genre">

View File

@ -1,6 +1,8 @@
@model MusicStore.Models.Album @model MusicStore.Models.Album
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Album - " + Model.Title; ViewBag.Title = "Album - " + Model.Title;
} }

View File

@ -1,5 +1,7 @@
@model IEnumerable<MusicStore.Models.Genre> @model IEnumerable<MusicStore.Models.Genre>
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Store"; ViewBag.Title = "Store";
} }
<h3>Browse Genres</h3> <h3>Browse Genres</h3>

View File

@ -2,6 +2,8 @@
@model MvcMusicStore.Models.Album @model MvcMusicStore.Models.Album
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Create"; ViewBag.Title = "Create";
} }

View File

@ -2,6 +2,8 @@
@model MvcMusicStore.Models.Album @model MvcMusicStore.Models.Album
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Delete"; ViewBag.Title = "Delete";
} }

View File

@ -2,6 +2,8 @@
@model MvcMusicStore.Models.Album @model MvcMusicStore.Models.Album
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Details"; ViewBag.Title = "Details";
} }

View File

@ -2,6 +2,8 @@
@model MvcMusicStore.Models.Album @model MvcMusicStore.Models.Album
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Edit"; ViewBag.Title = "Edit";
} }

View File

@ -14,6 +14,8 @@
} }
@{ @{
//Bug: Need to have a way to specify an application level layout page
Layout = "/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Index"; ViewBag.Title = "Index";
} }

BIN
src/MusicStore/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -15,6 +15,7 @@
"Microsoft.AspNet.Mvc.Rendering": "0.1-alpha-*", "Microsoft.AspNet.Mvc.Rendering": "0.1-alpha-*",
"Microsoft.AspNet.StaticFiles": "0.1-alpha-*", "Microsoft.AspNet.StaticFiles": "0.1-alpha-*",
"System.Security.Claims": "0.1-alpha-*", "System.Security.Claims": "0.1-alpha-*",
"System.Security.Principal": "4.0.0.0",
"Microsoft.AspNet.Security.DataProtection": "0.1-alpha-*", "Microsoft.AspNet.Security.DataProtection": "0.1-alpha-*",
"Microsoft.AspNet.Identity": "0.1-alpha-*", "Microsoft.AspNet.Identity": "0.1-alpha-*",
"Microsoft.AspNet.Identity.Entity": "0.1-alpha-*", "Microsoft.AspNet.Identity.Entity": "0.1-alpha-*",