Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Update #276 - Added MVC4 version of MVC Music Store as sample/test ap…

…plication.
  • Loading branch information...
commit e0f009699ac63d1e0727972986c41b56a0c28025 1 parent 3921822
@nikmd23 nikmd23 authored
Showing with 21,924 additions and 0 deletions.
  1. +8 −0 .gitignore
  2. +13 −0 Glimpse.All.sln
  3. BIN  source/Glimpse.Mvc4.MusicStore.Sample/App_Data/ASPNETDB_ReadOnly.mdf
  4. BIN  source/Glimpse.Mvc4.MusicStore.Sample/App_Data/ASPNETDB_log_ReadOnly.ldf
  5. BIN  source/Glimpse.Mvc4.MusicStore.Sample/App_Data/MvcMusicStore_ReadOnly.mdf
  6. BIN  source/Glimpse.Mvc4.MusicStore.Sample/App_Data/MvcMusicStore_log_ReadOnly.ldf
  7. +39 −0 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/AppConfig.cs
  8. +32 −0 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/AuthConfig.cs
  9. +26 −0 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/BundleConfig.cs
  10. +13 −0 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/FilterConfig.cs
  11. +23 −0 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/RouteConfig.cs
  12. +19 −0 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/WebApiConfig.cs
  13. +928 −0 source/Glimpse.Mvc4.MusicStore.Sample/Content/Site.css
  14. +426 −0 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/AccountController.cs
  15. +85 −0 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/CheckoutController.cs
  16. +35 −0 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/HomeController.cs
  17. +101 −0 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/ShoppingCartController.cs
  18. +57 −0 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/StoreController.cs
  19. +131 −0 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/StoreManagerController.cs
  20. +50 −0 source/Glimpse.Mvc4.MusicStore.Sample/Filters/InitializeSimpleMembershipAttribute.cs
  21. +328 −0 source/Glimpse.Mvc4.MusicStore.Sample/Glimpse.Mvc4.MusicStore.Sample.csproj
  22. +1 −0  source/Glimpse.Mvc4.MusicStore.Sample/Global.asax
  23. +30 −0 source/Glimpse.Mvc4.MusicStore.Sample/Global.asax.cs
  24. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/accent.png
  25. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/bullet.png
  26. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/heroAccent.png
  27. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/home-showcase.png
  28. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/logo.png
  29. +303 −0 source/Glimpse.Mvc4.MusicStore.Sample/Images/logo.svg
  30. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList0.png
  31. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList1.png
  32. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList2.png
  33. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList3.png
  34. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList4.png
  35. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList5.png
  36. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList6.png
  37. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList7.png
  38. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList8.png
  39. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/orderedList9.png
  40. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Images/placeholder.png
  41. +112 −0 source/Glimpse.Mvc4.MusicStore.Sample/Images/placeholder.svg
  42. +97 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/AccountModels.cs
  43. +36 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/Album.cs
  44. +13 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/Artist.cs
  45. +19 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/Cart.cs
  46. +12 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/Genre.cs
  47. +14 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/MusicStoreEntities.cs
  48. +68 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/Order.cs
  49. +14 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/OrderDetail.cs
  50. +827 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/SampleData.cs
  51. +195 −0 source/Glimpse.Mvc4.MusicStore.Sample/Models/ShoppingCart.cs
  52. +35 −0 source/Glimpse.Mvc4.MusicStore.Sample/Properties/AssemblyInfo.cs
  53. BIN  source/Glimpse.Mvc4.MusicStore.Sample/Scripts/_references.js
  54. +2,657 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery-1.9.1.intellisense.js
  55. +9,597 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery-1.9.1.js
  56. +5 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery-1.9.1.min.js
  57. +1 −0  source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery-1.9.1.min.map
  58. +163 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery.unobtrusive-ajax.js
  59. +5 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery.unobtrusive-ajax.min.js
  60. +1,288 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery.validate-vsdoc.js
  61. +1,207 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery.validate.js
  62. +4 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery.validate.min.js
  63. +367 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery.validate.unobtrusive.js
  64. +5 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/jquery.validate.unobtrusive.min.js
  65. +1,265 −0 source/Glimpse.Mvc4.MusicStore.Sample/Scripts/modernizr-2.5.3.js
  66. +11 −0 source/Glimpse.Mvc4.MusicStore.Sample/ViewModels/ShoppingCartRemoveViewModel.cs
  67. +11 −0 source/Glimpse.Mvc4.MusicStore.Sample/ViewModels/ShoppingCartViewModel.cs
  68. +36 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/ExternalLoginConfirmation.cshtml
  69. +8 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/ExternalLoginFailure.cshtml
  70. +50 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/Login.cshtml
  71. +32 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/Manage.cshtml
  72. +37 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/Register.cshtml
  73. +27 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/_ChangePasswordPartial.cshtml
  74. +25 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/_ExternalLoginsListPartial.cshtml
  75. +34 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/_RemoveExternalLoginsPartial.cshtml
  76. +26 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Account/_SetPasswordPartial.cshtml
  77. +32 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Checkout/AddressAndPayment.cshtml
  78. +13 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Checkout/Complete.cshtml
  79. +34 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Home/About.cshtml
  80. +50 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Home/Contact.cshtml
  81. +21 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Home/Index.cshtml
  82. +11 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Shared/Error.cshtml
  83. +52 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Shared/_Layout.cshtml
  84. +14 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Shared/_LoginPartial.cshtml
  85. +8 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/ShoppingCart/CartSummary.cshtml
  86. +91 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/ShoppingCart/Index.cshtml
  87. +23 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Store/Browse.cshtml
  88. +30 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Store/Details.cshtml
  89. +16 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Store/GenreMenu.cshtml
  90. +14 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Store/Index.cshtml
  91. +67 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/StoreManager/Create.cshtml
  92. +21 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/StoreManager/Delete.cshtml
  93. +50 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/StoreManager/Details.cshtml
  94. +69 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/StoreManager/Edit.cshtml
  95. +61 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/StoreManager/Index.cshtml
  96. +59 −0 source/Glimpse.Mvc4.MusicStore.Sample/Views/Web.config
  97. +3 −0  source/Glimpse.Mvc4.MusicStore.Sample/Views/_ViewStart.cshtml
  98. +30 −0 source/Glimpse.Mvc4.MusicStore.Sample/Web.Debug.config
  99. +31 −0 source/Glimpse.Mvc4.MusicStore.Sample/Web.Release.config
  100. +143 −0 source/Glimpse.Mvc4.MusicStore.Sample/Web.config
  101. BIN  source/Glimpse.Mvc4.MusicStore.Sample/favicon.ico
  102. +30 −0 source/Glimpse.Mvc4.MusicStore.Sample/packages.config
View
8 .gitignore
@@ -39,3 +39,11 @@ Help/
/source/Glimpse.AspNet.Net45/NuSpec/lib/net45/Glimpse.AspNet.dll
/source/Glimpse.AspNet.Net45/NuSpec/lib/net45/Glimpse.AspNet.pdb
+
+/source/Glimpse.Mvc4.MusicStore.Sample/App_Data/ASPNETDB.MDF
+
+/source/Glimpse.Mvc4.MusicStore.Sample/App_Data/ASPNETDB_log.ldf
+
+/source/Glimpse.Mvc4.MusicStore.Sample/App_Data/MvcMusicStore.mdf
+
+/source/Glimpse.Mvc4.MusicStore.Sample/App_Data/MvcMusicStore_log.ldf
View
13 Glimpse.All.sln
@@ -62,6 +62,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Glimpse.AspNet.Net45", "sou
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Glimpse.Mvc3", "source\Glimpse.Mvc3\Glimpse.Mvc3.csproj", "{585C1C27-8D37-4CB6-BD0F-464487845661}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Glimpse.Mvc4.MusicStore.Sample", "source\Glimpse.Mvc4.MusicStore.Sample\Glimpse.Mvc4.MusicStore.Sample.csproj", "{C2C38EE9-01B7-4929-B7E9-086077D1AB58}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -282,12 +284,23 @@ Global
{585C1C27-8D37-4CB6-BD0F-464487845661}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{585C1C27-8D37-4CB6-BD0F-464487845661}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{585C1C27-8D37-4CB6-BD0F-464487845661}.Release|x86.ActiveCfg = Release|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{32DCD27D-A84C-4250-B657-408B3620A9AC} = {CCFACE51-18FA-4C5D-9F89-EC58881786A9}
+ {C2C38EE9-01B7-4929-B7E9-086077D1AB58} = {CCFACE51-18FA-4C5D-9F89-EC58881786A9}
{9923BFBD-EA73-4719-A418-213003862550} = {A3097EAF-9D1B-416A-822E-F679D768BC55}
{76714E46-AFE9-49F0-AEE8-C8A966195914} = {A3097EAF-9D1B-416A-822E-F679D768BC55}
{FE12BC0C-CD22-4D24-BFC7-13ED1C428BAD} = {A3097EAF-9D1B-416A-822E-F679D768BC55}
View
BIN  source/Glimpse.Mvc4.MusicStore.Sample/App_Data/ASPNETDB_ReadOnly.mdf
Binary file not shown
View
BIN  source/Glimpse.Mvc4.MusicStore.Sample/App_Data/ASPNETDB_log_ReadOnly.ldf
Binary file not shown
View
BIN  source/Glimpse.Mvc4.MusicStore.Sample/App_Data/MvcMusicStore_ReadOnly.mdf
Binary file not shown
View
BIN  source/Glimpse.Mvc4.MusicStore.Sample/App_Data/MvcMusicStore_log_ReadOnly.ldf
Binary file not shown
View
39 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/AppConfig.cs
@@ -0,0 +1,39 @@
+using MvcMusicStore.Filters;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using System.Web;
+using System.Web.Security;
+using WebMatrix.WebData;
+
+namespace MvcMusicStore
+{
+ public static class AppConfig
+ {
+ public static void Configure()
+ {
+ System.Data.Entity.Database.SetInitializer(new MvcMusicStore.Models.SampleData());
+
+ CreateAdminUser();
+ }
+
+ private static void CreateAdminUser()
+ {
+ string _username = ConfigurationManager.AppSettings["DefaultAdminUsername"];
+ string _password = ConfigurationManager.AppSettings["DefaultAdminPassword"];
+ string _role = "Administrator";
+
+ new InitializeSimpleMembershipAttribute().OnActionExecuting(null);
+
+ if (!WebSecurity.UserExists(_username))
+ WebSecurity.CreateUserAndAccount(_username, _password);
+
+ if (!Roles.RoleExists(_role))
+ Roles.CreateRole(_role);
+
+ if (!Roles.IsUserInRole(_username, _role))
+ Roles.AddUserToRole(_username, _role);
+ }
+ }
+}
View
32 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/AuthConfig.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Web.WebPages.OAuth;
+using MvcMusicStore.Models;
+
+namespace MvcMusicStore
+{
+ public static class AuthConfig
+ {
+ public static void RegisterAuth()
+ {
+ // To let users of this site log in using their accounts from other sites such as Microsoft, Facebook, and Twitter,
+ // you must update this site. For more information visit http://go.microsoft.com/fwlink/?LinkID=252166
+
+ //OAuthWebSecurity.RegisterMicrosoftClient(
+ // clientId: "",
+ // clientSecret: "");
+
+ //OAuthWebSecurity.RegisterTwitterClient(
+ // consumerKey: "",
+ // consumerSecret: "");
+
+ //OAuthWebSecurity.RegisterFacebookClient(
+ // appId: "",
+ // appSecret: "");
+
+ //OAuthWebSecurity.RegisterGoogleClient();
+ }
+ }
+}
View
26 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/BundleConfig.cs
@@ -0,0 +1,26 @@
+using System.Web;
+using System.Web.Optimization;
+
+namespace MvcMusicStore
+{
+ public class BundleConfig
+ {
+ // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
+ public static void RegisterBundles(BundleCollection bundles)
+ {
+ bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
+ "~/Scripts/jquery-{version}.js"));
+
+ bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
+ "~/Scripts/jquery.unobtrusive*",
+ "~/Scripts/jquery.validate*"));
+
+ // Use the development version of Modernizr to develop with and learn from. Then, when you're
+ // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
+ bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
+ "~/Scripts/modernizr-*"));
+
+ bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));
+ }
+ }
+}
View
13 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/FilterConfig.cs
@@ -0,0 +1,13 @@
+using System.Web;
+using System.Web.Mvc;
+
+namespace MvcMusicStore
+{
+ public class FilterConfig
+ {
+ public static void RegisterGlobalFilters(GlobalFilterCollection filters)
+ {
+ filters.Add(new HandleErrorAttribute());
+ }
+ }
+}
View
23 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/RouteConfig.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Routing;
+
+namespace MvcMusicStore
+{
+ public class RouteConfig
+ {
+ public static void RegisterRoutes(RouteCollection routes)
+ {
+ routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
+
+ routes.MapRoute(
+ name: "Default",
+ url: "{controller}/{action}/{id}",
+ defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
+ );
+ }
+ }
+}
View
19 source/Glimpse.Mvc4.MusicStore.Sample/App_Start/WebApiConfig.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web.Http;
+
+namespace MvcMusicStore
+{
+ public static class WebApiConfig
+ {
+ public static void Register(HttpConfiguration config)
+ {
+ config.Routes.MapHttpRoute(
+ name: "DefaultApi",
+ routeTemplate: "api/{controller}/{id}",
+ defaults: new { id = RouteParameter.Optional }
+ );
+ }
+ }
+}
View
928 source/Glimpse.Mvc4.MusicStore.Sample/Content/Site.css
@@ -0,0 +1,928 @@
+html {
+ background-color: #e2e2e2;
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ background-color: #fff;
+ border-top: solid 10px #000;
+ color: #333;
+ font-size: .85em;
+ font-family: "Segoe UI", Verdana, Helvetica, Sans-Serif;
+ margin: 0;
+ padding: 0;
+}
+
+a {
+ color: #333;
+ outline: none;
+ padding-left: 3px;
+ padding-right: 3px;
+ text-decoration: underline;
+}
+
+ a:link, a:visited,
+ a:active, a:hover {
+ color: #333;
+ }
+
+ a:hover {
+ background-color: #c7d1d6;
+ }
+
+header, footer, hgroup,
+nav, section {
+ display: block;
+}
+
+mark {
+ background-color: #a6dbed;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+.float-left {
+ float: left;
+}
+
+.float-right {
+ float: right;
+}
+
+.clear-fix:after {
+ content: ".";
+ clear: both;
+ display: block;
+ height: 0;
+ visibility: hidden;
+}
+
+h1, h2, h3,
+h4, h5, h6 {
+ color: #000;
+ margin-bottom: 0;
+ padding-bottom: 0;
+}
+
+h1 {
+ font-size: 2em;
+}
+
+h2 {
+ font-size: 1.75em;
+}
+
+h3 {
+ font-size: 1.2em;
+}
+
+h4 {
+ font-size: 1.1em;
+}
+
+h5, h6 {
+ font-size: 1em;
+}
+
+ h5 a:link, h5 a:visited, h5 a:active {
+ padding: 0;
+ text-decoration: none;
+ }
+
+
+/* main layout
+----------------------------------------------------------*/
+.content-wrapper {
+ margin: 0 auto;
+ max-width: 960px;
+}
+
+#body {
+ background-color: #efeeef;
+ clear: both;
+ padding-bottom: 35px;
+}
+
+.main-content {
+ background: url("../Images/accent.png") no-repeat;
+ padding-left: 10px;
+ padding-top: 30px;
+}
+
+.featured + .main-content {
+ background: url("../Images/heroAccent.png") no-repeat;
+}
+
+header .content-wrapper {
+ padding-top: 20px;
+}
+
+footer {
+ clear: both;
+ background-color: #e2e2e2;
+ font-size: .8em;
+ height: 100px;
+}
+
+
+/* site title
+----------------------------------------------------------*/
+.site-title {
+ color: #c8c8c8;
+ font-family: Rockwell, Consolas, "Courier New", Courier, monospace;
+ font-size: 2.3em;
+ margin: 0;
+}
+
+ .site-title a, .site-title a:hover, .site-title a:active {
+ background: none;
+ color: #c8c8c8;
+ outline: none;
+ text-decoration: none;
+ }
+
+
+/* login
+----------------------------------------------------------*/
+#login {
+ display: block;
+ font-size: .85em;
+ margin: 0 0 10px;
+ text-align: right;
+}
+
+ #login a {
+ background-color: #d3dce0;
+ margin-left: 10px;
+ margin-right: 3px;
+ padding: 2px 3px;
+ text-decoration: none;
+ }
+
+ #login a.username {
+ background: none;
+ margin: 0;
+ padding: 0;
+ text-decoration: underline;
+ }
+
+ #login ul {
+ margin: 0;
+ }
+
+ #login li {
+ display: inline;
+ list-style: none;
+ }
+
+
+/* menu
+----------------------------------------------------------*/
+ul#menu {
+ font-size: 1.3em;
+ font-weight: 600;
+ margin: 0 0 5px;
+ padding: 0;
+ text-align: right;
+}
+
+ ul#menu li {
+ display: inline;
+ list-style: none;
+ padding-left: 15px;
+ }
+
+ ul#menu li a {
+ background: none;
+ color: #999;
+ text-decoration: none;
+ }
+
+ ul#menu li a:hover {
+ color: #333;
+ text-decoration: none;
+ }
+
+
+/* page elements
+----------------------------------------------------------*/
+/* featured */
+.featured {
+ background-color: #fff;
+}
+
+ .featured .content-wrapper {
+ background-color: #7ac0da;
+ background-image: -ms-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%);
+ background-image: -o-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%);
+ background-image: -webkit-gradient(linear, left top, right top, color-stop(0, #7ac0da), color-stop(1, #a4d4e6));
+ background-image: -webkit-linear-gradient(left, #7ac0da 0%, #a4d4e6 100%);
+ background-image: linear-gradient(left, #7ac0da 0%, #a4d4e6 100%);
+ color: #3e5667;
+ padding: 20px 40px 30px 40px;
+ }
+
+ .featured hgroup.title h1, .featured hgroup.title h2 {
+ color: #fff;
+ }
+
+ .featured p {
+ font-size: 1.1em;
+ }
+
+/* page titles */
+hgroup.title {
+ margin-bottom: 10px;
+}
+
+ hgroup.title h1, hgroup.title h2 {
+ display: inline;
+ }
+
+ hgroup.title h2 {
+ font-weight: normal;
+ margin-left: 3px;
+ }
+
+/* features */
+section.feature {
+ width: 300px;
+ float: left;
+ padding: 10px;
+}
+
+/* ordered list */
+ol.round {
+ list-style-type: none;
+ padding-left: 0;
+}
+
+ ol.round li {
+ margin: 25px 0;
+ padding-left: 45px;
+ }
+
+ ol.round li.zero {
+ background: url("../Images/orderedList0.png") no-repeat;
+ }
+
+ ol.round li.one {
+ background: url("../Images/orderedList1.png") no-repeat;
+ }
+
+ ol.round li.two {
+ background: url("../Images/orderedList2.png") no-repeat;
+ }
+
+ ol.round li.three {
+ background: url("../Images/orderedList3.png") no-repeat;
+ }
+
+ ol.round li.four {
+ background: url("../Images/orderedList4.png") no-repeat;
+ }
+
+ ol.round li.five {
+ background: url("../Images/orderedList5.png") no-repeat;
+ }
+
+ ol.round li.six {
+ background: url("../Images/orderedList6.png") no-repeat;
+ }
+
+ ol.round li.seven {
+ background: url("../Images/orderedList7.png") no-repeat;
+ }
+
+ ol.round li.eight {
+ background: url("../Images/orderedList8.png") no-repeat;
+ }
+
+ ol.round li.nine {
+ background: url("../Images/orderedList9.png") no-repeat;
+ }
+
+/* content */
+article {
+ float: left;
+ width: 70%;
+}
+
+aside {
+ float: right;
+ width: 25%;
+}
+
+ aside ul {
+ list-style: none;
+ padding: 0;
+ }
+
+ aside ul li {
+ background: url("../Images/bullet.png") no-repeat 0 50%;
+ padding: 2px 0 2px 20px;
+ }
+
+.label {
+ font-weight: 700;
+}
+
+/* login page */
+#loginForm {
+ border-right: solid 2px #c8c8c8;
+ float: left;
+ width: 55%;
+}
+
+ #loginForm .validation-error {
+ display: block;
+ margin-left: 15px;
+ }
+
+ #loginForm .validation-summary-errors ul {
+ margin: 0;
+ padding: 0;
+ }
+
+ #loginForm .validation-summary-errors li {
+ display: inline;
+ list-style: none;
+ margin: 0;
+ }
+
+ #loginForm input {
+ width: 250px;
+ }
+
+ #loginForm input[type="checkbox"],
+ #loginForm input[type="submit"],
+ #loginForm input[type="button"],
+ #loginForm button {
+ width: auto;
+ }
+
+#socialLoginForm {
+ margin-left: 40px;
+ float: left;
+ width: 40%;
+}
+
+ #socialLoginForm h2 {
+ margin-bottom: 5px;
+ }
+
+#socialLoginList button {
+ margin-bottom: 12px;
+}
+
+#logoutForm {
+ display: inline;
+}
+
+/* contact */
+.contact h3 {
+ font-size: 1.2em;
+}
+
+.contact p {
+ margin: 5px 0 0 10px;
+}
+
+.contact iframe {
+ border: 1px solid #333;
+ margin: 5px 0 0 10px;
+}
+
+/* forms */
+fieldset {
+ border: none;
+ margin: 0;
+ padding: 0;
+}
+
+ fieldset legend {
+ display: none;
+ }
+
+ fieldset ol {
+ padding: 0;
+ list-style: none;
+ }
+
+ fieldset ol li {
+ padding-bottom: 5px;
+ }
+
+label {
+ display: block;
+ font-size: 1.2em;
+ font-weight: 600;
+}
+
+ label.checkbox {
+ display: inline;
+ }
+
+input, textarea {
+ border: 1px solid #e2e2e2;
+ background: #fff;
+ color: #333;
+ font-size: 1.2em;
+ margin: 5px 0 6px 0;
+ padding: 5px;
+ width: 300px;
+}
+
+textarea {
+ font-family: inherit;
+ width: 500px;
+}
+
+ input:focus, textarea:focus {
+ border: 1px solid #7ac0da;
+ }
+
+input[type="checkbox"] {
+ background: transparent;
+ border: inherit;
+ width: auto;
+}
+
+input[type="submit"],
+input[type="button"],
+button {
+ background-color: #d3dce0;
+ border: 1px solid #787878;
+ cursor: pointer;
+ font-size: 1.2em;
+ font-weight: 600;
+ padding: 7px;
+ margin-right: 8px;
+ width: auto;
+}
+
+td input[type="submit"],
+td input[type="button"],
+td button {
+ font-size: 1em;
+ padding: 4px;
+ margin-right: 4px;
+}
+
+/* info and errors */
+.message-info {
+ border: 1px solid;
+ clear: both;
+ padding: 10px 20px;
+}
+
+.message-error {
+ clear: both;
+ color: #e80c4d;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin: 20px 0 10px 0;
+}
+
+.message-success {
+ color: #7ac0da;
+ font-size: 1.3em;
+ font-weight: bold;
+ margin: 20px 0 10px 0;
+}
+
+.error {
+ color: #e80c4d;
+}
+
+/* styles for validation helpers */
+.field-validation-error {
+ color: #e80c4d;
+ font-weight: bold;
+}
+
+.field-validation-valid {
+ display: none;
+}
+
+input.input-validation-error {
+ border: 1px solid #e80c4d;
+}
+
+input[type="checkbox"].input-validation-error {
+ border: 0 none;
+}
+
+.validation-summary-errors {
+ color: #e80c4d;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.validation-summary-valid {
+ display: none;
+}
+
+
+/* tables
+----------------------------------------------------------*/
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ margin-top: 0.75em;
+ border: 0 none;
+}
+
+th {
+ font-size: 1.2em;
+ text-align: left;
+ border: none 0px;
+ padding-left: 0;
+}
+
+ th a {
+ display: block;
+ position: relative;
+ }
+
+ th a:link, th a:visited, th a:active, th a:hover {
+ color: #333;
+ font-weight: 600;
+ text-decoration: none;
+ padding: 0;
+ }
+
+ th a:hover {
+ color: #000;
+ }
+
+ th.asc a, th.desc a {
+ margin-right: .75em;
+ }
+
+ th.asc a:after, th.desc a:after {
+ display: block;
+ position: absolute;
+ right: 0em;
+ top: 0;
+ font-size: 0.75em;
+ }
+
+ th.asc a:after {
+ content: '';
+ }
+
+ th.desc a:after {
+ content: '';
+ }
+
+td {
+ padding: 0.25em 2em 0.25em 0em;
+ border: 0 none;
+}
+
+tr.pager td {
+ padding: 0 0.25em 0 0;
+}
+
+
+/********************
+* Mobile Styles *
+********************/
+@media only screen and (max-width: 850px) {
+
+ /* header
+ ----------------------------------------------------------*/
+ header .float-left,
+ header .float-right {
+ float: none;
+ }
+
+ /* logo */
+ header .site-title {
+ margin: 10px;
+ text-align: center;
+ }
+
+ /* login */
+ #login {
+ font-size: .85em;
+ margin: 0 0 12px;
+ text-align: center;
+ }
+
+ #login ul {
+ margin: 5px 0;
+ padding: 0;
+ }
+
+ #login li {
+ display: inline;
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ }
+
+ #login a {
+ background: none;
+ color: #999;
+ font-weight: 600;
+ margin: 2px;
+ padding: 0;
+ }
+
+ #login a:hover {
+ color: #333;
+ }
+
+ /* menu */
+ nav {
+ margin-bottom: 5px;
+ }
+
+ ul#menu {
+ margin: 0;
+ padding: 0;
+ text-align: center;
+ }
+
+ ul#menu li {
+ margin: 0;
+ padding: 0;
+ }
+
+
+ /* main layout
+ ----------------------------------------------------------*/
+ .main-content,
+ .featured + .main-content {
+ background-position: 10px 0;
+ }
+
+ .content-wrapper {
+ padding-right: 10px;
+ padding-left: 10px;
+ }
+
+ .featured .content-wrapper {
+ padding: 10px;
+ }
+
+ /* page content */
+ article, aside {
+ float: none;
+ width: 100%;
+ }
+
+ /* ordered list */
+ ol.round {
+ list-style-type: none;
+ padding-left: 0;
+ }
+
+ ol.round li {
+ padding-left: 10px;
+ margin: 25px 0;
+ }
+
+ ol.round li.zero,
+ ol.round li.one,
+ ol.round li.two,
+ ol.round li.three,
+ ol.round li.four,
+ ol.round li.five,
+ ol.round li.six,
+ ol.round li.seven,
+ ol.round li.eight,
+ ol.round li.nine {
+ background: none;
+ }
+
+ /* features */
+ section.feature {
+ float: none;
+ padding: 10px;
+ width: auto;
+ }
+
+ section.feature img {
+ color: #999;
+ content: attr(alt);
+ font-size: 1.5em;
+ font-weight: 600;
+ }
+
+ /* forms */
+ input {
+ width: 90%;
+ }
+
+ /* login page */
+ #loginForm {
+ border-right: none;
+ float: none;
+ width: auto;
+ }
+
+ #loginForm .validation-error {
+ display: block;
+ margin-left: 15px;
+ }
+
+ #socialLoginForm {
+ margin-left: 0;
+ float: none;
+ width: auto;
+ }
+
+
+ /* footer
+ ----------------------------------------------------------*/
+ footer .float-left,
+ footer .float-right {
+ float: none;
+ }
+
+ footer {
+ text-align: center;
+ height: auto;
+ padding: 10px 0;
+ }
+
+ footer p {
+ margin: 0;
+ }
+}
+
+/**************************
+* Music Store Additions *
+**************************/
+
+p.site-title {
+ background: url(../Images/logo.svg) no-repeat;
+ vertical-align: bottom;
+ font-size: 20px;
+ width: 100%;
+ padding-top: 40px;
+}
+
+html.no-svg p.site-title {
+ background: url(../Images/logo.png) no-repeat;
+}
+
+section.main-content, div#body {
+ background-color: #FBF9EF;
+}
+
+#promotion img {
+ max-width: 100%;
+ display: block;
+ margin: auto;
+}
+
+#top-albums h3 {
+ margin-left: 50px;
+}
+
+h2 {
+ color: #5e5b54;
+}
+
+h2, h3 {
+ margin-bottom: 10px;
+ font-size: 16px;
+ font-style: italic;
+ font-weight: bold;
+}
+
+h3 {
+ color: #9B9993;
+}
+
+ header h1 a, h3 em {
+ color: #5E5B54;
+ }
+
+nav#categories {
+ display: block;
+ max-width: 960px;
+ margin: auto;
+}
+
+ul#album-list {
+ list-style-type: none;
+}
+
+ ul#album-list li {
+ display: inline;
+ width: 105px;
+ height: 150px;
+ float: left;
+ text-align: center;
+ margin: 10px;
+ font-weight: bold;
+ color: #5e5b54;
+ }
+
+ ul#album-list li img:hover {
+ box-shadow: 1px 1px 7px #777;
+ }
+
+ ul#album-list li img {
+ box-shadow: 1px 1px 5px #999;
+ border: none;
+ }
+
+ ul#album-list li a, ul#album-details li a {
+ text-decoration:none;
+ }
+
+ ul#album-list li a:hover {
+ background: none;
+ text-shadow: 1px 1px 2px #bbb;
+ color: #363430;
+ }
+
+#categories {
+ padding: 10px;
+}
+
+ #categories ul {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+ text-align: center;
+ }
+
+ #categories ul li {
+ display: inline-block;
+ }
+
+ #categories ul li a {
+ text-decoration: none;
+ padding: .1em .4em .2em .4em;
+ color: #fff;
+ background-color: #3f3c37;
+ display: block;
+ margin: .1em;
+ min-width: 4.3em;
+ }
+
+ #categories ul li a:hover {
+ color: #fff;
+ background-color: hsl(40, 7%, 45%);
+ box-shadow: 1px 1px 2px #aaa;
+ }
+
+div#album-details p {
+ margin: 0;
+ color: #5e5b54;
+ font-weight: bold;
+}
+
+.main-content {
+ padding-top: 0;
+ background-image: none;
+ padding-left: 50px;
+}
+
+header, footer {
+ padding: 0 50px;
+}
+
+footer {
+ max-height: 25px;
+}
+
+table#cart-summary tr td {
+ border-top: 1px solid black;
+ min-width: 100px;
+}
+
+.button, input[type=submit] {
+ margin-top: 10px;
+ display: inline-block;
+ padding: 5px;
+ margin-top: 10px;
+ border: 1px;
+ background: #5e5b54;
+ color: #fff;
+ font-weight: bold;
+}
+
+ .button a {
+ color: #fff !important;
+ text-decoration: none;
+ }
+
+div.editor-field select {
+ height: 30px;
+ width: 310px;
+}
+
+@media only screen and (max-width: 850px) {
+ p.site-title {
+ background-position: center top;
+ }
+}
View
426 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/AccountController.cs
@@ -0,0 +1,426 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Transactions;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Security;
+using DotNetOpenAuth.AspNet;
+using Microsoft.Web.WebPages.OAuth;
+using WebMatrix.WebData;
+using MvcMusicStore.Filters;
+using MvcMusicStore.Models;
+
+namespace MvcMusicStore.Controllers
+{
+ [Authorize]
+ [InitializeSimpleMembership]
+ public class AccountController : Controller
+ {
+ //
+ // GET: /Account/Login
+
+ [AllowAnonymous]
+ public ActionResult Login(string returnUrl)
+ {
+ ViewBag.ReturnUrl = returnUrl;
+ return View();
+ }
+
+ //
+ // POST: /Account/Login
+
+ [HttpPost]
+ [AllowAnonymous]
+ [ValidateAntiForgeryToken]
+ public ActionResult Login(LoginModel model, string returnUrl)
+ {
+ if (ModelState.IsValid && WebSecurity.Login(
+ model.UserName, model.Password, persistCookie: model.RememberMe))
+ {
+ // Migrate the user's shopping cart
+ MigrateShoppingCart(model.UserName);
+ return RedirectToLocal(returnUrl);
+ }
+
+ // If we got this far, something failed, redisplay form
+ ModelState.AddModelError("", "The user name or password provided is incorrect.");
+ return View(model);
+ }
+
+ private void MigrateShoppingCart(string UserName)
+ {
+ 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;
+ }
+
+ //
+ // POST: /Account/LogOff
+
+ [HttpPost]
+ [ValidateAntiForgeryToken]
+ public ActionResult LogOff()
+ {
+ WebSecurity.Logout();
+
+ return RedirectToAction("Index", "Home");
+ }
+
+ //
+ // GET: /Account/Register
+
+ [AllowAnonymous]
+ public ActionResult Register()
+ {
+ return View();
+ }
+
+ //
+ // POST: /Account/Register
+
+ [HttpPost]
+ [AllowAnonymous]
+ [ValidateAntiForgeryToken]
+ public ActionResult Register(RegisterModel model)
+ {
+ if (ModelState.IsValid)
+ {
+ // Attempt to register the user
+ try
+ {
+ WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
+ WebSecurity.Login(model.UserName, model.Password);
+
+ // Migrate the newly registered user's shopping cart
+ MigrateShoppingCart(model.UserName);
+
+ return RedirectToAction("Index", "Home");
+ }
+ catch (MembershipCreateUserException e)
+ {
+ ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
+ }
+ }
+
+ // If we got this far, something failed, redisplay form
+ return View(model);
+ }
+
+ //
+ // POST: /Account/Disassociate
+
+ [HttpPost]
+ [ValidateAntiForgeryToken]
+ public ActionResult Disassociate(string provider, string providerUserId)
+ {
+ string ownerAccount = OAuthWebSecurity.GetUserName(provider, providerUserId);
+ ManageMessageId? message = null;
+
+ // Only disassociate the account if the currently logged in user is the owner
+ if (ownerAccount == User.Identity.Name)
+ {
+ // Use a transaction to prevent the user from deleting their last login credential
+ using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.Serializable }))
+ {
+ bool hasLocalAccount = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
+ if (hasLocalAccount || OAuthWebSecurity.GetAccountsFromUserName(User.Identity.Name).Count > 1)
+ {
+ OAuthWebSecurity.DeleteAccount(provider, providerUserId);
+ scope.Complete();
+ message = ManageMessageId.RemoveLoginSuccess;
+ }
+ }
+ }
+
+ return RedirectToAction("Manage", new { Message = message });
+ }
+
+ //
+ // GET: /Account/Manage
+
+ public 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."
+ : "";
+ ViewBag.HasLocalPassword = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
+ ViewBag.ReturnUrl = Url.Action("Manage");
+ return View();
+ }
+
+ //
+ // POST: /Account/Manage
+
+ [HttpPost]
+ [ValidateAntiForgeryToken]
+ public ActionResult Manage(LocalPasswordModel model)
+ {
+ bool hasLocalAccount = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
+ ViewBag.HasLocalPassword = hasLocalAccount;
+ ViewBag.ReturnUrl = Url.Action("Manage");
+ if (hasLocalAccount)
+ {
+ if (ModelState.IsValid)
+ {
+ // ChangePassword will throw an exception rather than return false in certain failure scenarios.
+ bool changePasswordSucceeded;
+ try
+ {
+ changePasswordSucceeded = WebSecurity.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword);
+ }
+ catch (Exception)
+ {
+ changePasswordSucceeded = false;
+ }
+
+ if (changePasswordSucceeded)
+ {
+ return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
+ }
+ else
+ {
+ ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
+ }
+ }
+ }
+ else
+ {
+ // User does not have a local password so remove any validation errors caused by a missing
+ // OldPassword field
+ ModelState state = ModelState["OldPassword"];
+ if (state != null)
+ {
+ state.Errors.Clear();
+ }
+
+ if (ModelState.IsValid)
+ {
+ try
+ {
+ WebSecurity.CreateAccount(User.Identity.Name, model.NewPassword);
+ return RedirectToAction("Manage", new { Message = ManageMessageId.SetPasswordSuccess });
+ }
+ catch (Exception e)
+ {
+ ModelState.AddModelError("", e);
+ }
+ }
+ }
+
+ // 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)
+ {
+ return new ExternalLoginResult(provider, Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
+ }
+
+ //
+ // GET: /Account/ExternalLoginCallback
+
+ [AllowAnonymous]
+ public ActionResult ExternalLoginCallback(string returnUrl)
+ {
+ AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
+ if (!result.IsSuccessful)
+ {
+ return RedirectToAction("ExternalLoginFailure");
+ }
+
+ if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
+ {
+ return RedirectToLocal(returnUrl);
+ }
+
+ if (User.Identity.IsAuthenticated)
+ {
+ // If the current user is logged in add the new account
+ OAuthWebSecurity.CreateOrUpdateAccount(result.Provider, result.ProviderUserId, User.Identity.Name);
+ return RedirectToLocal(returnUrl);
+ }
+ else
+ {
+ // User is new, ask for their desired membership name
+ string loginData = OAuthWebSecurity.SerializeProviderUserId(result.Provider, result.ProviderUserId);
+ ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
+ ViewBag.ReturnUrl = returnUrl;
+ return View("ExternalLoginConfirmation", new RegisterExternalLoginModel { UserName = result.UserName, ExternalLoginData = loginData });
+ }
+ }
+
+ //
+ // POST: /Account/ExternalLoginConfirmation
+
+ [HttpPost]
+ [AllowAnonymous]
+ [ValidateAntiForgeryToken]
+ public ActionResult ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
+ {
+ string provider = null;
+ string providerUserId = null;
+
+ if (User.Identity.IsAuthenticated || !OAuthWebSecurity.TryDeserializeProviderUserId(model.ExternalLoginData, out provider, out providerUserId))
+ {
+ return RedirectToAction("Manage");
+ }
+
+ if (ModelState.IsValid)
+ {
+ // Insert a new user into the database
+ using (UsersContext db = new UsersContext())
+ {
+ UserProfile user = db.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == model.UserName.ToLower());
+ // Check if user already exists
+ if (user == null)
+ {
+ // Insert name into the profile table
+ db.UserProfiles.Add(new UserProfile { UserName = model.UserName });
+ db.SaveChanges();
+
+ OAuthWebSecurity.CreateOrUpdateAccount(provider, providerUserId, model.UserName);
+ OAuthWebSecurity.Login(provider, providerUserId, createPersistentCookie: false);
+
+ return RedirectToLocal(returnUrl);
+ }
+ else
+ {
+ ModelState.AddModelError("UserName", "User name already exists. Please enter a different user name.");
+ }
+ }
+ }
+
+ ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(provider).DisplayName;
+ ViewBag.ReturnUrl = returnUrl;
+ return View(model);
+ }
+
+ //
+ // GET: /Account/ExternalLoginFailure
+
+ [AllowAnonymous]
+ public ActionResult ExternalLoginFailure()
+ {
+ return View();
+ }
+
+ [AllowAnonymous]
+ [ChildActionOnly]
+ public ActionResult ExternalLoginsList(string returnUrl)
+ {
+ ViewBag.ReturnUrl = returnUrl;
+ return PartialView("_ExternalLoginsListPartial", OAuthWebSecurity.RegisteredClientData);
+ }
+
+ [ChildActionOnly]
+ public ActionResult RemoveExternalLogins()
+ {
+ ICollection<OAuthAccount> accounts = OAuthWebSecurity.GetAccountsFromUserName(User.Identity.Name);
+ List<ExternalLogin> externalLogins = new List<ExternalLogin>();
+ foreach (OAuthAccount account in accounts)
+ {
+ AuthenticationClientData clientData = OAuthWebSecurity.GetOAuthClientData(account.Provider);
+
+ externalLogins.Add(new ExternalLogin
+ {
+ Provider = account.Provider,
+ ProviderDisplayName = clientData.DisplayName,
+ ProviderUserId = account.ProviderUserId,
+ });
+ }
+
+ ViewBag.ShowRemoveButton = externalLogins.Count > 1 || OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
+ return PartialView("_RemoveExternalLoginsPartial", externalLogins);
+ }
+
+ #region Helpers
+ private ActionResult RedirectToLocal(string returnUrl)
+ {
+ if (Url.IsLocalUrl(returnUrl))
+ {
+ return Redirect(returnUrl);
+ }
+ else
+ {
+ return RedirectToAction("Index", "Home");
+ }
+ }
+
+ public enum ManageMessageId
+ {
+ ChangePasswordSuccess,
+ SetPasswordSuccess,
+ RemoveLoginSuccess,
+ }
+
+ internal class ExternalLoginResult : ActionResult
+ {
+ public ExternalLoginResult(string provider, string returnUrl)
+ {
+ Provider = provider;
+ ReturnUrl = returnUrl;
+ }
+
+ public string Provider { get; private set; }
+ public string ReturnUrl { get; private set; }
+
+ public override void ExecuteResult(ControllerContext context)
+ {
+ OAuthWebSecurity.RequestAuthentication(Provider, ReturnUrl);
+ }
+ }
+
+ private static string ErrorCodeToString(MembershipCreateStatus createStatus)
+ {
+ // See http://go.microsoft.com/fwlink/?LinkID=177550 for
+ // a full list of status codes.
+ switch (createStatus)
+ {
+ case MembershipCreateStatus.DuplicateUserName:
+ return "User name already exists. Please enter a different user name.";
+
+ case MembershipCreateStatus.DuplicateEmail:
+ return "A user name for that e-mail address already exists. Please enter a different e-mail address.";
+
+ case MembershipCreateStatus.InvalidPassword:
+ return "The password provided is invalid. Please enter a valid password value.";
+
+ case MembershipCreateStatus.InvalidEmail:
+ return "The e-mail address provided is invalid. Please check the value and try again.";
+
+ case MembershipCreateStatus.InvalidAnswer:
+ return "The password retrieval answer provided is invalid. Please check the value and try again.";
+
+ case MembershipCreateStatus.InvalidQuestion:
+ return "The password retrieval question provided is invalid. Please check the value and try again.";
+
+ case MembershipCreateStatus.InvalidUserName:
+ return "The user name provided is invalid. Please check the value and try again.";
+
+ case MembershipCreateStatus.ProviderError:
+ return "The authentication provider returned an error. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
+
+ case MembershipCreateStatus.UserRejected:
+ return "The user creation request has been canceled. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
+
+ default:
+ return "An unknown error occurred. Please verify your entry and try again. If the problem persists, please contact your system administrator.";
+ }
+ }
+ #endregion
+ }
+}
View
85 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/CheckoutController.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Linq;
+using System.Web.Mvc;
+using MvcMusicStore.Models;
+
+namespace MvcMusicStore.Controllers
+{
+ [Authorize]
+ public class CheckoutController : Controller
+ {
+ MusicStoreEntities storeDB = new MusicStoreEntities();
+ const string PromoCode = "FREE";
+
+ //
+ // GET: /Checkout/
+
+ public ActionResult AddressAndPayment()
+ {
+ return View();
+ }
+
+ //
+ // POST: /Checkout/AddressAndPayment
+
+ [HttpPost]
+ public ActionResult AddressAndPayment(FormCollection values)
+ {
+ var order = new Order();
+ TryUpdateModel(order);
+
+ try
+ {
+ if (string.Equals(values["PromoCode"], PromoCode,
+ StringComparison.OrdinalIgnoreCase) == false)
+ {
+ return View(order);
+ }
+ else
+ {
+ order.Username = User.Identity.Name;
+ order.OrderDate = DateTime.Now;
+
+ //Add the Order
+ storeDB.Orders.Add(order);
+
+ //Process the order
+ var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
+ cart.CreateOrder(order);
+
+ // Save all changes
+ storeDB.SaveChanges();
+
+ return RedirectToAction("Complete",
+ new { id = order.OrderId });
+ }
+
+ }
+ catch
+ {
+ //Invalid - redisplay with errors
+ return View(order);
+ }
+ }
+
+ //
+ // GET: /Checkout/Complete
+
+ public ActionResult Complete(int id)
+ {
+ // Validate customer owns this order
+ bool isValid = storeDB.Orders.Any(
+ o => o.OrderId == id &&
+ o.Username == User.Identity.Name);
+
+ if (isValid)
+ {
+ return View(id);
+ }
+ else
+ {
+ return View("Error");
+ }
+ }
+ }
+}
View
35 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/HomeController.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using MvcMusicStore.Models;
+
+namespace MvcMusicStore.Controllers
+{
+ public class HomeController : Controller
+ {
+ private MusicStoreEntities storeDB = new MusicStoreEntities();
+ //
+ // GET: /Home/
+
+ public ActionResult Index()
+ {
+ // Get most popular albums
+ var albums = GetTopSellingAlbums(6);
+
+ return View(albums);
+ }
+
+
+ private List<Album> GetTopSellingAlbums(int count)
+ {
+ // 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();
+ }
+ }
+}
View
101 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/ShoppingCartController.cs
@@ -0,0 +1,101 @@
+using System.Linq;
+using System.Web.Mvc;
+using MvcMusicStore.Models;
+using MvcMusicStore.ViewModels;
+
+namespace MvcMusicStore.Controllers
+{
+ public class ShoppingCartController : Controller
+ {
+ MusicStoreEntities storeDB = new MusicStoreEntities();
+
+ //
+ // GET: /ShoppingCart/
+
+ public ActionResult Index()
+ {
+ var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
+
+ // Set up our ViewModel
+ var viewModel = new ShoppingCartViewModel
+ {
+ CartItems = cart.GetCartItems(),
+ CartTotal = cart.GetTotal()
+ };
+
+ // Return the view
+ return View(viewModel);
+ }
+
+ //
+ // GET: /ShoppingCart/AddToCart/5
+
+ public ActionResult AddToCart(int id)
+ {
+
+ // Retrieve the album from the database
+ var addedAlbum = storeDB.Albums
+ .Single(album => album.AlbumId == id);
+
+ // Add it to the shopping cart
+ var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
+
+ cart.AddToCart(addedAlbum);
+
+ storeDB.SaveChanges();
+
+ // Go back to the main store page for more shopping
+ return RedirectToAction("Index");
+ }
+
+ //
+ // AJAX: /ShoppingCart/RemoveFromCart/5
+
+ [HttpPost]
+ public ActionResult RemoveFromCart(int id)
+ {
+ // Retrieve the current user's shopping cart
+ var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
+
+ // Get the name of the album to display confirmation
+ string albumName = storeDB.Carts
+ .Single(item => item.RecordId == id).Album.Title;
+
+ // Remove from cart
+ int itemCount = cart.RemoveFromCart(id);
+
+ storeDB.SaveChanges();
+
+ string removed = (itemCount > 0) ? " 1 copy of " : string.Empty;
+
+ // Display the confirmation message
+
+ var results = new ShoppingCartRemoveViewModel
+ {
+ Message = removed + albumName +
+ " has been removed from your shopping cart.",
+ CartTotal = cart.GetTotal(),
+ CartCount = cart.GetCount(),
+ ItemCount = itemCount,
+ DeleteId = id
+ };
+
+ return Json(results);
+ }
+
+ [ChildActionOnly]
+ public ActionResult CartSummary()
+ {
+ var cart = ShoppingCart.GetCart(storeDB, this.HttpContext);
+
+ var cartItems = cart.GetCartItems()
+ .Select(a => a.Album.Title)
+ .OrderBy(x => x);
+
+ ViewBag.CartCount = cartItems.Count();
+ ViewBag.CartSummary = string.Join("\n", cartItems.Distinct());
+
+ return PartialView("CartSummary");
+ }
+ }
+}
View
57 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/StoreController.cs
@@ -0,0 +1,57 @@
+using MvcMusicStore.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+
+namespace MvcMusicStore.Controllers
+{
+ public class StoreController : Controller
+ {
+ MusicStoreEntities storeDB = new MusicStoreEntities();
+ //
+ // GET: /Store/
+
+ public ActionResult Index()
+ {
+ var genres = storeDB.Genres.ToList();
+
+ return View(genres);
+ }
+
+
+ //
+ // GET: /Store/Browse?genre=Disco
+
+ public 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);
+ }
+
+ public ActionResult Details(int id)
+ {
+ var album = storeDB.Albums.Find(id);
+
+ return View(album);
+ }
+
+ [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(genres);
+ }
+ }
+}
View
131 source/Glimpse.Mvc4.MusicStore.Sample/Controllers/StoreManagerController.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Entity;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using MvcMusicStore.Models;
+
+namespace MvcMusicStore.Controllers
+{
+ [Authorize(Roles = "Administrator")]
+ public class StoreManagerController : Controller
+ {
+ private MusicStoreEntities db = new MusicStoreEntities();
+
+ //
+ // GET: /StoreManager/
+
+ public ActionResult Index()
+ {
+ var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist)
+ .OrderBy(a => a.Price);
+ return View(albums.ToList());
+ }
+
+ //
+ // GET: /StoreManager/Details/5
+
+ public ActionResult Details(int id = 0)
+ {
+ Album album = db.Albums.Find(id);
+ if (album == null)
+ {
+ return HttpNotFound();
+ }
+ return View(album);
+ }
+
+ //
+ // GET: /StoreManager/Create
+
+ public ActionResult Create()
+ {
+ ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");
+ ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
+ return View();
+ }
+
+ //
+ // POST: /StoreManager/Create
+
+ [HttpPost]
+ public ActionResult Create(Album album)
+ {
+ if (ModelState.IsValid)
+ {
+ db.Albums.Add(album);
+ db.SaveChanges();
+ 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);
+ }
+
+ //
+ // GET: /StoreManager/Edit/5
+
+ public ActionResult Edit(int id = 0)
+ {
+ Album album = db.Albums.Find(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);
+ }
+
+ //
+ // POST: /StoreManager/Edit/5
+
+ [HttpPost]
+ public ActionResult Edit(Album album)
+ {
+ if (ModelState.IsValid)
+ {
+ db.Entry(album).State = EntityState.Modified;
+ db.SaveChanges();
+ 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);
+ }
+
+ //
+ // GET: /StoreManager/Delete/5
+
+ public ActionResult Delete(int id = 0)
+ {
+ Album album = db.Albums.Find(id);
+ if (album == null)
+ {
+ return HttpNotFound();
+ }
+ return View(album);
+ }
+
+ //
+ // POST: /StoreManager/Delete/5
+
+ [HttpPost, ActionName("Delete")]
+ public ActionResult DeleteConfirmed(int id)
+ {
+ Album album = db.Albums.Find(id);
+ db.Albums.Remove(album);
+ db.SaveChanges();
+ return RedirectToAction("Index");
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ db.Dispose();
+ base.Dispose(disposing);
+ }
+ }
+}
View
50 source/Glimpse.Mvc4.MusicStore.Sample/Filters/InitializeSimpleMembershipAttribute.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Data.Entity;
+using System.Data.Entity.Infrastructure;
+using System.Threading;
+using System.Web.Mvc;
+using WebMatrix.WebData;
+using MvcMusicStore.Models;
+
+namespace MvcMusicStore.Filters
+{
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
+ public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
+ {
+ private static SimpleMembershipInitializer _initializer;
+ private static object _initializerLock = new object();
+ private static bool _isInitialized;
+
+ public override void OnActionExecuting(ActionExecutingContext filterContext)
+ {
+ // Ensure ASP.NET Simple Membership is initialized only once per app start
+ LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
+ }
+
+ private class SimpleMembershipInitializer
+ {
+ public SimpleMembershipInitializer()
+ {
+ Database.SetInitializer<UsersContext>(null);
+
+ try
+ {
+ using (var context = new UsersContext())
+ {
+ if (!context.Database.Exists())
+ {
+ // Create the SimpleMembership database without Entity Framework migration schema
+ ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
+ }
+ }
+
+ WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
+ }
+ catch (Exception ex)
+ {
+ throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
+ }
+ }
+ }
+ }
+}
View
328 source/Glimpse.Mvc4.MusicStore.Sample/Glimpse.Mvc4.MusicStore.Sample.csproj
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>
+ </ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{C2C38EE9-01B7-4929-B7E9-086077D1AB58}</ProjectGuid>
+ <ProjectTypeGuids>{E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>MvcMusicStore</RootNamespace>
+ <AssemblyName>MvcMusicStore</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MvcBuildViews>false</MvcBuildViews>
+ <UseIISExpress>true</UseIISExpress>
+ <IISExpressSSLPort />
+ <IISExpressAnonymousAuthentication />
+ <IISExpressWindowsAuthentication />
+ <IISExpressUseClassicPipelineMode />
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Antlr3.Runtime">
+ <HintPath>..\..\packages\WebGrease.1.1.0\lib\Antlr3.Runtime.dll</HintPath>
+ </Reference>
+ <Reference Include="DotNetOpenAuth.AspNet">
+ <HintPath>..\..\packages\DotNetOpenAuth.AspNet.4.2.2.13055\lib\net45-full\DotNetOpenAuth.AspNet.dll</HintPath>
+ </Reference>
+ <Reference Include="DotNetOpenAuth.Core">
+ <HintPath>..\..\packages\DotNetOpenAuth.Core.4.2.2.13055\lib\net45-full\DotNetOpenAuth.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="DotNetOpenAuth.OAuth">
+ <HintPath>..\..\packages\DotNetOpenAuth.OAuth.Core.4.2.2.13055\lib\net45-full\DotNetOpenAuth.OAuth.dll</HintPath>
+ </Reference>
+ <Reference Include="DotNetOpenAuth.OAuth.Consumer">
+ <HintPath>..\..\packages\DotNetOpenAuth.OAuth.Consumer.4.2.2.13055\lib\net45-full\DotNetOpenAuth.OAuth.Consumer.dll</HintPath>
+ </Reference>
+ <Reference Include="DotNetOpenAuth.OpenId">
+ <HintPath>..\..\packages\DotNetOpenAuth.OpenId.Core.4.2.2.13055\lib\net45-full\DotNetOpenAuth.OpenId.dll</HintPath>
+ </Reference>
+ <Reference Include="DotNetOpenAuth.OpenId.RelyingParty">
+ <HintPath>..\..\packages\DotNetOpenAuth.OpenId.RelyingParty.4.2.2.13055\lib\net45-full\DotNetOpenAuth.OpenId.RelyingParty.dll</HintPath>
+ </Reference>
+ <Reference Include="EntityFramework">
+ <HintPath>..\..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Data.Entity" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Web.DynamicData" />
+ <Reference Include="System.Web.Entity" />
+ <Reference Include="System.Web.ApplicationServices" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Web.Optimization">
+ <HintPath>..\..\packages\Microsoft.AspNet.Web.Optimization.1.0.0\lib\net40\System.Web.Optimization.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Web.Extensions" />
+ <Reference Include="System.Web.Abstractions" />
+ <Reference Include="System.Web.Routing" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Configuration" />
+ <Reference Include="System.Transactions" />
+ <Reference Include="System.Web.Services" />
+ <Reference Include="System.EnterpriseServices" />
+ <Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Net.Http">
+ </Reference>
+ <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Net.Http.WebRequest">
+ </Reference>
+ <Reference Include="System.Web.Helpers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.Helpers.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.Http.WebHost, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.20710.0\lib\net40\System.Web.Http.WebHost.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.Mvc.4.0.20710.0\lib\net40\System.Web.Mvc.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.Razor.2.0.20710.0\lib\net40\System.Web.Razor.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Deployment.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.WebPages.2.0.20710.0\lib\net40\System.Web.WebPages.Razor.dll</HintPath>
+ </Reference>
+ <Reference Include="WebGrease">
+ <HintPath>..\..\packages\WebGrease.1.1.0\lib\WebGrease.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="WebMatrix.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.WebPages.Data.2.0.20710.0\lib\net40\WebMatrix.Data.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.Web.WebPages.OAuth, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.WebPages.OAuth.2.0.20710.0\lib\net40\Microsoft.Web.WebPages.OAuth.dll</HintPath>
+ </Reference>
+ <Reference Include="WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <Private>True</Private>
+ <HintPath>..\packages\Microsoft.AspNet.WebPages.WebData.2.0.20710.0\lib\net40\WebMatrix.WebData.dll</HintPath>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="App_Start\AuthConfig.cs" />
+ <Compile Include="App_Start\BundleConfig.cs" />
+ <Compile Include="App_Start\FilterConfig.cs" />
+ <Compile Include="App_Start\AppConfig.cs" />
+ <Compile Include="App_Start\RouteConfig.cs" />
+ <Compile Include="App_Start\WebApiConfig.cs" />
+ <Compile Include="Controllers\AccountController.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Controllers\CheckoutController.cs" />
+ <Compile Include="Controllers\HomeController.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Controllers\ShoppingCartController.cs" />
+ <Compile Include="Controllers\StoreController.cs" />
+ <Compile Include="Controllers\StoreManagerController.cs" />
+ <Compile Include="Filters\InitializeSimpleMembershipAttribute.cs" />
+ <Compile Include="Global.asax.cs">
+ <DependentUpon>Global.asax</DependentUpon>
+ </Compile>
+ <Compile Include="Models\AccountModels.cs" />
+ <Compile Include="Models\Album.cs" />
+ <Compile Include="Models\Artist.cs" />
+ <Compile Include="Models\Cart.cs" />
+ <Compile Include="Models\Genre.cs" />
+ <Compile Include="Models\MusicStoreEntities.cs" />
+ <Compile Include="Models\Order.cs" />
+ <Compile Include="Models\OrderDetail.cs" />
+ <Compile Include="Models\SampleData.cs" />
+ <Compile Include="Models\ShoppingCart.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ViewModels\ShoppingCartRemoveViewModel.cs" />
+ <Compile Include="ViewModels\ShoppingCartViewModel.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Images\home-showcase.png" />
+ <Content Include="Images\logo.png" />
+ <Content Include="Images\logo.svg" />
+ <Content Include="Images\placeholder.png" />
+ <Content Include="favicon.ico" />
+ <Content Include="Global.asax" />
+ <None Include="Scripts\jquery-1.9.1.intellisense.js" />
+ <Content Include="Scripts\jquery-1.9.1.js" />
+ <Content Include="Scripts\jquery-1.9.1.min.js" />
+ <Content Include="Scripts\jquery-1.9.1.min.map" />
+ <Content Include="Scripts\jquery.unobtrusive-ajax.js" />
+ <Content Include="Scripts\jquery.unobtrusive-ajax.min.js" />
+ <None Include="Scripts\jquery.validate-vsdoc.js" />
+ <Content Include="Scripts\jquery.validate.js" />
+ <Content Include="Scripts\jquery.validate.min.js" />
+ <Content Include="Scripts\jquery.validate.unobtrusive.js" />
+ <Content Include="Scripts\jquery.validate.unobtrusive.min.js" />
+ <Content Include="Scripts\knockout-2.1.0.debug.js" />
+ <Content Include="Scripts\knockout-2.1.0.js" />
+ <Content Include="Scripts\modernizr-2.5.3.js" />
+ <Content Include="Web.config">
+ <SubType>Designer</SubType>
+ </Content>
+ <Content Include="Web.Debug.config">
+ <DependentUpon>Web.config</DependentUpon>
+ </Content>
+ <Content Include="Web.Release.config">
+ <DependentUpon>Web.config</DependentUpon>
+ </Content>
+ <Content Include="Content\Site.css" />
+ <Content Include="Scripts\_references.js" />
+ <Content Include="Images\accent.png" />
+ <Content Include="Images\bullet.png" />
+ <Content Include="Images\heroAccent.png" />
+ <Content Include="Images\orderedList0.png" />
+ <Content Include="Images\orderedList1.png