├── .gitattributes ├── .gitignore ├── MyShop ├── MyShop.Core │ ├── Contracts │ │ ├── IBasketService.cs │ │ ├── IOrderService.cs │ │ └── IRepository.cs │ ├── Models │ │ ├── BaseEntity.cs │ │ ├── Basket.cs │ │ ├── BasketItem.cs │ │ ├── Customer.cs │ │ ├── Order.cs │ │ ├── OrderItem.cs │ │ ├── Product.cs │ │ └── ProductCategory.cs │ ├── MyShop.Core.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ └── ViewModels │ │ ├── BasketItemViewModel.cs │ │ ├── BasketSummaryViewModel.cs │ │ ├── ProductListViewModel.cs │ │ └── ProductManagerViewModel.cs ├── MyShop.DataAccess.InMemory │ ├── InMemoryRepository.cs │ ├── MyShop.DataAccess.InMemory.csproj │ └── Properties │ │ └── AssemblyInfo.cs ├── MyShop.DataAccess.SQL │ ├── App.config │ ├── DataContext.cs │ ├── Migrations │ │ ├── 201711071327340_Initial.Designer.cs │ │ ├── 201711071327340_Initial.cs │ │ ├── 201711071327340_Initial.resx │ │ ├── 201711091321341_AddBasket.Designer.cs │ │ ├── 201711091321341_AddBasket.cs │ │ ├── 201711091321341_AddBasket.resx │ │ ├── 201801032024566_AddCustomer.Designer.cs │ │ ├── 201801032024566_AddCustomer.cs │ │ ├── 201801032024566_AddCustomer.resx │ │ ├── 201801101446455_AddedOrders.Designer.cs │ │ ├── 201801101446455_AddedOrders.cs │ │ ├── 201801101446455_AddedOrders.resx │ │ └── Configuration.cs │ ├── MyShop.DataAccess.SQL.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SQLRepository.cs │ └── packages.config ├── MyShop.Services │ ├── BasketService.cs │ ├── MyShop.Services.csproj │ ├── OrderService.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── MyShop.WebUI.Tests │ ├── App.config │ ├── Controllers │ │ ├── BasketControllerTests.cs │ │ └── HomeControllerTests.cs │ ├── Mocks │ │ ├── MockContext.cs │ │ └── MockHttpContext.cs │ ├── MyShop.WebUI.Tests.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ └── packages.config ├── MyShop.WebUI │ ├── App_Start │ │ ├── BundleConfig.cs │ │ ├── FilterConfig.cs │ │ ├── IdentityConfig.cs │ │ ├── RouteConfig.cs │ │ ├── Startup.Auth.cs │ │ ├── UnityConfig.cs │ │ └── UnityMvcActivator.cs │ ├── ApplicationInsights.config │ ├── Content │ │ ├── ProductImages │ │ │ ├── 720780c9-f6ca-4ebc-8647-4164dea5a3ab.jpg │ │ │ └── 7acd2efb-4ac1-457e-b19d-079b430e25f1.jpg │ │ ├── Site.css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── Controllers │ │ ├── AccountController.cs │ │ ├── AdminController.cs │ │ ├── BasketController.cs │ │ ├── HomeController.cs │ │ ├── ManageController.cs │ │ ├── OrderManagerController.cs │ │ ├── ProductCategoryManagerController.cs │ │ └── ProductManagerController.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Models │ │ ├── AccountViewModels.cs │ │ ├── IdentityModels.cs │ │ └── ManageViewModels.cs │ ├── MyShop.WebUI.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Scripts │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── jquery-3.2.1.intellisense.js │ │ ├── jquery-3.2.1.js │ │ ├── jquery-3.2.1.min.js │ │ ├── jquery-3.2.1.min.map │ │ ├── jquery-3.2.1.slim.js │ │ ├── jquery-3.2.1.slim.min.js │ │ ├── jquery-3.2.1.slim.min.map │ │ ├── jquery.validate-vsdoc.js │ │ ├── jquery.validate.js │ │ ├── jquery.validate.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ ├── jquery.validate.unobtrusive.min.js │ │ ├── modernizr-2.8.3.js │ │ ├── respond.js │ │ ├── respond.matchmedia.addListener.js │ │ ├── respond.matchmedia.addListener.min.js │ │ └── respond.min.js │ ├── Startup.cs │ ├── Views │ │ ├── Account │ │ │ ├── ConfirmEmail.cshtml │ │ │ ├── ExternalLoginConfirmation.cshtml │ │ │ ├── ExternalLoginFailure.cshtml │ │ │ ├── ForgotPassword.cshtml │ │ │ ├── ForgotPasswordConfirmation.cshtml │ │ │ ├── Login.cshtml │ │ │ ├── Register.cshtml │ │ │ ├── ResetPassword.cshtml │ │ │ ├── ResetPasswordConfirmation.cshtml │ │ │ ├── SendCode.cshtml │ │ │ ├── VerifyCode.cshtml │ │ │ └── _ExternalLoginsListPartial.cshtml │ │ ├── Admin │ │ │ └── Index.cshtml │ │ ├── Basket │ │ │ ├── BasketSummary.cshtml │ │ │ ├── Checkout.cshtml │ │ │ ├── Index.cshtml │ │ │ └── ThankYou.cshtml │ │ ├── Home │ │ │ ├── About.cshtml │ │ │ ├── Contact.cshtml │ │ │ ├── Details.cshtml │ │ │ └── Index.cshtml │ │ ├── Manage │ │ │ ├── AddPhoneNumber.cshtml │ │ │ ├── ChangePassword.cshtml │ │ │ ├── Index.cshtml │ │ │ ├── ManageLogins.cshtml │ │ │ ├── SetPassword.cshtml │ │ │ └── VerifyPhoneNumber.cshtml │ │ ├── OrderManager │ │ │ ├── Index.cshtml │ │ │ ├── OrderItems.cshtml │ │ │ └── UpdateOrder.cshtml │ │ ├── ProductCategoryManager │ │ │ ├── Create.cshtml │ │ │ ├── Delete.cshtml │ │ │ ├── Edit.cshtml │ │ │ └── Index.cshtml │ │ ├── ProductManager │ │ │ ├── Create.cshtml │ │ │ ├── Delete.cshtml │ │ │ ├── Edit.cshtml │ │ │ └── Index.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ ├── Lockout.cshtml │ │ │ ├── _Layout.cshtml │ │ │ └── _LoginPartial.cshtml │ │ ├── Web.config │ │ └── _ViewStart.cshtml │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── favicon.ico │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── packages.config └── MyShop.sln └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Contracts/IBasketService.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.ViewModels; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Web; 8 | 9 | namespace MyShop.Core.Contracts 10 | { 11 | public interface IBasketService 12 | { 13 | void AddToBasket(HttpContextBase httpContext, string productId); 14 | void RemoveFromBasket(HttpContextBase httpContext, string itemId); 15 | List GetBasketItems(HttpContextBase httpContext); 16 | BasketSummaryViewModel GetBasketSummary(HttpContextBase httpContext); 17 | void ClearBasket(HttpContextBase httpContext); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Contracts/IOrderService.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Models; 2 | using MyShop.Core.ViewModels; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace MyShop.Core.Contracts 10 | { 11 | public interface IOrderService 12 | { 13 | void CreateOrder(Order baseOrder, List basketItems); 14 | List GetOrderList(); 15 | Order GetOrder(string Id); 16 | void UpdateOrder(Order updatedOrder); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Contracts/IRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using MyShop.Core.Models; 3 | 4 | namespace MyShop.Core.Contracts 5 | { 6 | public interface IRepository where T : BaseEntity 7 | { 8 | IQueryable Collection(); 9 | void Commit(); 10 | void Delete(string Id); 11 | T Find(string Id); 12 | void Insert(T t); 13 | void Update(T t); 14 | } 15 | } -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Models/BaseEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.Models 8 | { 9 | public abstract class BaseEntity 10 | { 11 | public string Id { get; set; } 12 | public DateTimeOffset CreatedAt { get; set; } 13 | 14 | public BaseEntity() { 15 | this.Id = Guid.NewGuid().ToString(); 16 | this.CreatedAt = DateTime.Now; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Models/Basket.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.Models 8 | { 9 | public class Basket : BaseEntity 10 | { 11 | public virtual ICollection BasketItems { get; set; } 12 | 13 | public Basket() { 14 | this.BasketItems = new List(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Models/BasketItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.Models 8 | { 9 | public class BasketItem : BaseEntity 10 | { 11 | public string BasketId { get; set; } 12 | public string ProductId { get; set; } 13 | public int Quanity { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Models/Customer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.Models 8 | { 9 | public class Customer : BaseEntity 10 | { 11 | public string UserId { get; set; } 12 | public string FirstName { get; set; } 13 | public string LastName { get; set; } 14 | public string Email { get; set; } 15 | public string Street { get; set; } 16 | public string City { get; set; } 17 | public string State { get; set; } 18 | public string ZipCode { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Models/Order.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.Models 8 | { 9 | public class Order : BaseEntity 10 | { 11 | public Order() { 12 | this.OrderItems = new List(); 13 | } 14 | 15 | public string FirstName { get; set; } 16 | public string Surname { get; set; } 17 | public string Email { get; set; } 18 | public string Street { get; set; } 19 | public string City { get; set; } 20 | public string State { get; set; } 21 | public string ZipCode { get; set; } 22 | public string OrderStatus { get; set; } 23 | public virtual ICollection OrderItems { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Models/OrderItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.Models 8 | { 9 | public class OrderItem : BaseEntity 10 | { 11 | public string OrderId { get; set; } 12 | public string ProductId { get; set; } 13 | public string ProductName { get; set; } 14 | public decimal Price { get; set; } 15 | public string Image { get; set; } 16 | public int Quanity { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Models/Product.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace MyShop.Core.Models 10 | { 11 | public class Product : BaseEntity 12 | { 13 | [StringLength(20)] 14 | [DisplayName("Product Name")] 15 | public string Name { get; set; } 16 | public string Description { get; set; } 17 | 18 | [Range(0, 1000)] 19 | public decimal Price { get; set; } 20 | public string Category { get; set; } 21 | public string Image { get; set; } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Models/ProductCategory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.Models 8 | { 9 | public class ProductCategory : BaseEntity 10 | { 11 | public string Category { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/MyShop.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {9B029460-6F4E-46AE-9B88-08C5FE08C0A4} 8 | Library 9 | Properties 10 | MyShop.Core 11 | MyShop.Core 12 | v4.6.1 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MyShop.Core")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MyShop.Core")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9b029460-6f4e-46ae-9b88-08c5fe08c0a4")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/ViewModels/BasketItemViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.ViewModels 8 | { 9 | public class BasketItemViewModel 10 | { 11 | public string Id { get; set; } 12 | public int Quanity { get; set; } 13 | public string ProductName { get; set; } 14 | public decimal Price { get; set; } 15 | public string Image { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/ViewModels/BasketSummaryViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace MyShop.Core.ViewModels 8 | { 9 | public class BasketSummaryViewModel 10 | { 11 | public int BasketCount { get; set; } 12 | public decimal BasketTotal { get; set; } 13 | 14 | public BasketSummaryViewModel() { 15 | } 16 | 17 | public BasketSummaryViewModel(int basketCount, decimal basketTotal) { 18 | this.BasketCount = basketCount; 19 | this.BasketTotal = basketTotal; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/ViewModels/ProductListViewModel.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MyShop.Core.ViewModels 9 | { 10 | public class ProductListViewModel 11 | { 12 | public IEnumerable Products { get; set; } 13 | public IEnumerable ProductCategories { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MyShop/MyShop.Core/ViewModels/ProductManagerViewModel.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MyShop.Core.ViewModels 9 | { 10 | public class ProductManagerViewModel 11 | { 12 | public Product Product { get; set; } 13 | public IEnumerable ProductCategories { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.InMemory/InMemoryRepository.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Runtime.Caching; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace MyShop.DataAccess.InMemory 11 | { 12 | public class InMemoryRepository : IRepository where T : BaseEntity 13 | { 14 | ObjectCache cache = MemoryCache.Default; 15 | List items; 16 | string className; 17 | 18 | public InMemoryRepository() { 19 | className = typeof(T).Name; 20 | items = cache[className] as List; 21 | if (items == null) { 22 | items = new List(); 23 | } 24 | } 25 | 26 | public void Commit() 27 | { 28 | cache[className] = items; 29 | } 30 | 31 | public void Insert(T t) { 32 | items.Add(t); 33 | } 34 | 35 | public void Update(T t) { 36 | T tToUpdate = items.Find(i => i.Id == t.Id); 37 | 38 | if (tToUpdate != null) 39 | { 40 | tToUpdate = t; 41 | } 42 | else { 43 | throw new Exception(className + " Not found"); 44 | } 45 | } 46 | 47 | public T Find(string Id) { 48 | T t = items.Find(i => i.Id == Id); 49 | if (t != null) { 50 | return t; 51 | } 52 | else 53 | { 54 | throw new Exception(className + " Not found"); 55 | } 56 | } 57 | 58 | public IQueryable Collection() { 59 | return items.AsQueryable(); 60 | } 61 | 62 | public void Delete(string Id) { 63 | T tToDelete = items.Find(i => i.Id == Id); 64 | 65 | if (tToDelete != null) 66 | { 67 | items.Remove(tToDelete); 68 | } 69 | else 70 | { 71 | throw new Exception(className + " Not found"); 72 | } 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.InMemory/MyShop.DataAccess.InMemory.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E7FD92A1-7304-4F70-9BA5-E214CB28A863} 8 | Library 9 | Properties 10 | MyShop.DataAccess.InMemory 11 | MyShop.DataAccess.InMemory 12 | v4.6.1 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | {9b029460-6f4e-46ae-9b88-08c5fe08c0a4} 50 | MyShop.Core 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.InMemory/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MyShop.DataAccess.InMemory")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MyShop.DataAccess.InMemory")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e7fd92a1-7304-4f70-9ba5-e214cb28a863")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/DataContext.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Data.Entity; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace MyShop.DataAccess.SQL 10 | { 11 | public class DataContext : DbContext 12 | { 13 | public DataContext() 14 | : base("DefaultConnection") { 15 | 16 | } 17 | 18 | public DbSet Products { get; set; } 19 | public DbSet ProductCategories { get; set; } 20 | public DbSet Baskets { get; set; } 21 | public DbSet BasketItems { get; set; } 22 | public DbSet Customers { get; set; } 23 | public DbSet Orders { get; set; } 24 | public DbSet OrderItems { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/201711071327340_Initial.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace MyShop.DataAccess.SQL.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")] 10 | public sealed partial class Initial : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(Initial)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201711071327340_Initial"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/201711071327340_Initial.cs: -------------------------------------------------------------------------------- 1 | namespace MyShop.DataAccess.SQL.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class Initial : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateTable( 11 | "dbo.ProductCategories", 12 | c => new 13 | { 14 | Id = c.String(nullable: false, maxLength: 128), 15 | Category = c.String(), 16 | CreatedAt = c.DateTimeOffset(nullable: false, precision: 7), 17 | }) 18 | .PrimaryKey(t => t.Id); 19 | 20 | CreateTable( 21 | "dbo.Products", 22 | c => new 23 | { 24 | Id = c.String(nullable: false, maxLength: 128), 25 | Name = c.String(maxLength: 20), 26 | Description = c.String(), 27 | Price = c.Decimal(nullable: false, precision: 18, scale: 2), 28 | Category = c.String(), 29 | Image = c.String(), 30 | CreatedAt = c.DateTimeOffset(nullable: false, precision: 7), 31 | }) 32 | .PrimaryKey(t => t.Id); 33 | 34 | } 35 | 36 | public override void Down() 37 | { 38 | DropTable("dbo.Products"); 39 | DropTable("dbo.ProductCategories"); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/201711091321341_AddBasket.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace MyShop.DataAccess.SQL.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")] 10 | public sealed partial class AddBasket : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(AddBasket)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201711091321341_AddBasket"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/201711091321341_AddBasket.cs: -------------------------------------------------------------------------------- 1 | namespace MyShop.DataAccess.SQL.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class AddBasket : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateTable( 11 | "dbo.BasketItems", 12 | c => new 13 | { 14 | Id = c.String(nullable: false, maxLength: 128), 15 | BasketId = c.String(maxLength: 128), 16 | ProductId = c.String(), 17 | Quanity = c.Int(nullable: false), 18 | CreatedAt = c.DateTimeOffset(nullable: false, precision: 7), 19 | }) 20 | .PrimaryKey(t => t.Id) 21 | .ForeignKey("dbo.Baskets", t => t.BasketId) 22 | .Index(t => t.BasketId); 23 | 24 | CreateTable( 25 | "dbo.Baskets", 26 | c => new 27 | { 28 | Id = c.String(nullable: false, maxLength: 128), 29 | CreatedAt = c.DateTimeOffset(nullable: false, precision: 7), 30 | }) 31 | .PrimaryKey(t => t.Id); 32 | 33 | } 34 | 35 | public override void Down() 36 | { 37 | DropForeignKey("dbo.BasketItems", "BasketId", "dbo.Baskets"); 38 | DropIndex("dbo.BasketItems", new[] { "BasketId" }); 39 | DropTable("dbo.Baskets"); 40 | DropTable("dbo.BasketItems"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/201801032024566_AddCustomer.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace MyShop.DataAccess.SQL.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")] 10 | public sealed partial class AddCustomer : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(AddCustomer)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201801032024566_AddCustomer"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/201801032024566_AddCustomer.cs: -------------------------------------------------------------------------------- 1 | namespace MyShop.DataAccess.SQL.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class AddCustomer : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateTable( 11 | "dbo.Customers", 12 | c => new 13 | { 14 | Id = c.String(nullable: false, maxLength: 128), 15 | UserId = c.String(), 16 | FirstName = c.String(), 17 | LastName = c.String(), 18 | Email = c.String(), 19 | Street = c.String(), 20 | City = c.String(), 21 | State = c.String(), 22 | ZipCode = c.String(), 23 | CreatedAt = c.DateTimeOffset(nullable: false, precision: 7), 24 | }) 25 | .PrimaryKey(t => t.Id); 26 | 27 | } 28 | 29 | public override void Down() 30 | { 31 | DropTable("dbo.Customers"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/201801101446455_AddedOrders.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace MyShop.DataAccess.SQL.Migrations 3 | { 4 | using System.CodeDom.Compiler; 5 | using System.Data.Entity.Migrations; 6 | using System.Data.Entity.Migrations.Infrastructure; 7 | using System.Resources; 8 | 9 | [GeneratedCode("EntityFramework.Migrations", "6.2.0-61023")] 10 | public sealed partial class AddedOrders : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(AddedOrders)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201801101446455_AddedOrders"; } 17 | } 18 | 19 | string IMigrationMetadata.Source 20 | { 21 | get { return null; } 22 | } 23 | 24 | string IMigrationMetadata.Target 25 | { 26 | get { return Resources.GetString("Target"); } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/201801101446455_AddedOrders.cs: -------------------------------------------------------------------------------- 1 | namespace MyShop.DataAccess.SQL.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class AddedOrders : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateTable( 11 | "dbo.OrderItems", 12 | c => new 13 | { 14 | Id = c.String(nullable: false, maxLength: 128), 15 | OrderId = c.String(maxLength: 128), 16 | ProductId = c.String(), 17 | ProductName = c.String(), 18 | Price = c.Decimal(nullable: false, precision: 18, scale: 2), 19 | Image = c.String(), 20 | Quanity = c.Int(nullable: false), 21 | CreatedAt = c.DateTimeOffset(nullable: false, precision: 7), 22 | }) 23 | .PrimaryKey(t => t.Id) 24 | .ForeignKey("dbo.Orders", t => t.OrderId) 25 | .Index(t => t.OrderId); 26 | 27 | CreateTable( 28 | "dbo.Orders", 29 | c => new 30 | { 31 | Id = c.String(nullable: false, maxLength: 128), 32 | FirstName = c.String(), 33 | Surname = c.String(), 34 | Email = c.String(), 35 | Street = c.String(), 36 | City = c.String(), 37 | State = c.String(), 38 | ZipCode = c.String(), 39 | OrderStatus = c.String(), 40 | CreatedAt = c.DateTimeOffset(nullable: false, precision: 7), 41 | }) 42 | .PrimaryKey(t => t.Id); 43 | 44 | } 45 | 46 | public override void Down() 47 | { 48 | DropForeignKey("dbo.OrderItems", "OrderId", "dbo.Orders"); 49 | DropIndex("dbo.OrderItems", new[] { "OrderId" }); 50 | DropTable("dbo.Orders"); 51 | DropTable("dbo.OrderItems"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Migrations/Configuration.cs: -------------------------------------------------------------------------------- 1 | namespace MyShop.DataAccess.SQL.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity; 5 | using System.Data.Entity.Migrations; 6 | using System.Linq; 7 | 8 | internal sealed class Configuration : DbMigrationsConfiguration 9 | { 10 | public Configuration() 11 | { 12 | AutomaticMigrationsEnabled = false; 13 | } 14 | 15 | protected override void Seed(MyShop.DataAccess.SQL.DataContext context) 16 | { 17 | // This method will be called after migrating to the latest version. 18 | 19 | // You can use the DbSet.AddOrUpdate() helper extension method 20 | // to avoid creating duplicate seed data. 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/MyShop.DataAccess.SQL.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3A4704F8-042D-4450-A79A-AA096ED4F5CD} 8 | Library 9 | Properties 10 | MyShop.DataAccess.SQL 11 | MyShop.DataAccess.SQL 12 | v4.6.1 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll 35 | 36 | 37 | ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 201711071327340_Initial.cs 54 | 55 | 56 | 57 | 201711091321341_AddBasket.cs 58 | 59 | 60 | 61 | 201801032024566_AddCustomer.cs 62 | 63 | 64 | 65 | 201801101446455_AddedOrders.cs 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | {9B029460-6F4E-46AE-9B88-08C5FE08C0A4} 78 | MyShop.Core 79 | 80 | 81 | 82 | 83 | 201711071327340_Initial.cs 84 | 85 | 86 | 201711091321341_AddBasket.cs 87 | 88 | 89 | 201801032024566_AddCustomer.cs 90 | 91 | 92 | 201801101446455_AddedOrders.cs 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MyShop.DataAccess.SQL")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MyShop.DataAccess.SQL")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3a4704f8-042d-4450-a79a-aa096ed4f5cd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/SQLRepository.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Data.Entity; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace MyShop.DataAccess.SQL 11 | { 12 | public class SQLRepository : IRepository where T : BaseEntity 13 | { 14 | internal DataContext context; 15 | internal DbSet dbSet; 16 | 17 | public SQLRepository(DataContext context) { 18 | this.context = context; 19 | this.dbSet = context.Set(); 20 | } 21 | 22 | public IQueryable Collection() 23 | { 24 | return dbSet; 25 | } 26 | 27 | public void Commit() 28 | { 29 | context.SaveChanges(); 30 | } 31 | 32 | public void Delete(string Id) 33 | { 34 | var t = Find(Id); 35 | if (context.Entry(t).State == EntityState.Detached) 36 | dbSet.Attach(t); 37 | 38 | dbSet.Remove(t); 39 | } 40 | 41 | public T Find(string Id) 42 | { 43 | return dbSet.Find(Id); 44 | } 45 | 46 | public void Insert(T t) 47 | { 48 | dbSet.Add(t); 49 | } 50 | 51 | public void Update(T t) 52 | { 53 | dbSet.Attach(t); 54 | context.Entry(t).State = EntityState.Modified; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /MyShop/MyShop.DataAccess.SQL/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /MyShop/MyShop.Services/BasketService.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using MyShop.Core.ViewModels; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Web; 10 | 11 | namespace MyShop.Services 12 | { 13 | public class BasketService : IBasketService 14 | { 15 | IRepository productContext; 16 | IRepository basketContext; 17 | 18 | public const string BasketSessionName = "eCommerceBasket"; 19 | 20 | public BasketService(IRepository ProductContext, IRepository BasketContext) { 21 | this.basketContext = BasketContext; 22 | this.productContext = ProductContext; 23 | } 24 | 25 | private Basket GetBasket(HttpContextBase httpContext, bool createIfNull) { 26 | HttpCookie cookie = httpContext.Request.Cookies.Get(BasketSessionName); 27 | 28 | Basket basket = new Basket(); 29 | 30 | if (cookie != null) 31 | { 32 | string basketId = cookie.Value; 33 | if (!string.IsNullOrEmpty(basketId)) 34 | { 35 | basket = basketContext.Find(basketId); 36 | } 37 | else 38 | { 39 | if (createIfNull) 40 | { 41 | basket = CreateNewBasket(httpContext); 42 | } 43 | } 44 | } 45 | else { 46 | if (createIfNull) 47 | { 48 | basket = CreateNewBasket(httpContext); 49 | } 50 | } 51 | 52 | return basket; 53 | 54 | } 55 | 56 | private Basket CreateNewBasket(HttpContextBase httpContext) { 57 | Basket basket = new Basket(); 58 | basketContext.Insert(basket); 59 | basketContext.Commit(); 60 | 61 | HttpCookie cookie = new HttpCookie(BasketSessionName); 62 | cookie.Value = basket.Id; 63 | cookie.Expires = DateTime.Now.AddDays(1); 64 | httpContext.Response.Cookies.Add(cookie); 65 | 66 | return basket; 67 | } 68 | 69 | public void AddToBasket(HttpContextBase httpContext, string productId) { 70 | Basket basket = GetBasket(httpContext, true); 71 | BasketItem item = basket.BasketItems.FirstOrDefault(i => i.ProductId == productId); 72 | 73 | if (item == null) 74 | { 75 | item = new BasketItem() 76 | { 77 | BasketId = basket.Id, 78 | ProductId = productId, 79 | Quanity = 1 80 | }; 81 | 82 | basket.BasketItems.Add(item); 83 | } 84 | else { 85 | item.Quanity = item.Quanity + 1; 86 | } 87 | 88 | basketContext.Commit(); 89 | } 90 | 91 | public void RemoveFromBasket(HttpContextBase httpContext, string itemId) { 92 | Basket basket = GetBasket(httpContext, true); 93 | BasketItem item = basket.BasketItems.FirstOrDefault(i => i.Id == itemId); 94 | 95 | if (item != null) { 96 | basket.BasketItems.Remove(item); 97 | basketContext.Commit(); 98 | } 99 | } 100 | 101 | public List GetBasketItems(HttpContextBase httpContext) { 102 | Basket basket = GetBasket(httpContext, false); 103 | 104 | if (basket != null) 105 | { 106 | var results = (from b in basket.BasketItems 107 | join p in productContext.Collection() on b.ProductId equals p.Id 108 | select new BasketItemViewModel() 109 | { 110 | Id = b.Id, 111 | Quanity = b.Quanity, 112 | ProductName = p.Name, 113 | Image = p.Image, 114 | Price = p.Price 115 | } 116 | ).ToList(); 117 | 118 | return results; 119 | } 120 | else { 121 | return new List(); 122 | } 123 | } 124 | 125 | public BasketSummaryViewModel GetBasketSummary(HttpContextBase httpContext) { 126 | Basket basket = GetBasket(httpContext, false); 127 | BasketSummaryViewModel model = new BasketSummaryViewModel(0, 0); 128 | if (basket != null) 129 | { 130 | int? basketCount = (from item in basket.BasketItems 131 | select item.Quanity).Sum(); 132 | 133 | decimal? basketTotal = (from item in basket.BasketItems 134 | join p in productContext.Collection() on item.ProductId equals p.Id 135 | select item.Quanity * p.Price).Sum(); 136 | 137 | model.BasketCount = basketCount ?? 0; 138 | model.BasketTotal = basketTotal ?? decimal.Zero; 139 | 140 | return model; 141 | } 142 | else { 143 | return model; 144 | } 145 | } 146 | 147 | public void ClearBasket(HttpContextBase httpContext) { 148 | Basket basket = GetBasket(httpContext, false); 149 | basket.BasketItems.Clear(); 150 | basketContext.Commit(); 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /MyShop/MyShop.Services/MyShop.Services.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {462AA931-D9E7-4B8A-840B-C8026F2C0FC0} 8 | Library 9 | Properties 10 | MyShop.Services 11 | MyShop.Services 12 | v4.6.1 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {9b029460-6f4e-46ae-9b88-08c5fe08c0a4} 51 | MyShop.Core 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /MyShop/MyShop.Services/OrderService.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using MyShop.Core.ViewModels; 9 | 10 | namespace MyShop.Services 11 | { 12 | public class OrderService : IOrderService 13 | { 14 | IRepository orderContext; 15 | public OrderService(IRepository OrderContext) { 16 | this.orderContext = OrderContext; 17 | } 18 | 19 | public void CreateOrder(Order baseOrder, List basketItems) 20 | { 21 | foreach (var item in basketItems) { 22 | baseOrder.OrderItems.Add(new OrderItem() 23 | { 24 | ProductId = item.Id, 25 | Image = item.Image, 26 | Price = item.Price, 27 | ProductName = item.ProductName, 28 | Quanity = item.Quanity 29 | }); 30 | } 31 | 32 | orderContext.Insert(baseOrder); 33 | orderContext.Commit(); 34 | } 35 | 36 | public List GetOrderList() { 37 | return orderContext.Collection().ToList(); 38 | } 39 | 40 | public Order GetOrder(string Id) { 41 | return orderContext.Find(Id); 42 | } 43 | 44 | public void UpdateOrder(Order updatedOrder) { 45 | orderContext.Update(updatedOrder); 46 | orderContext.Commit(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /MyShop/MyShop.Services/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MyShop.Services")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MyShop.Services")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("462aa931-d9e7-4b8a-840b-c8026f2c0fc0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI.Tests/App.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI.Tests/Controllers/BasketControllerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using MyShop.Core.Contracts; 4 | using MyShop.Core.Models; 5 | using MyShop.WebUI.Tests.Mocks; 6 | using MyShop.Services; 7 | using System.Linq; 8 | using MyShop.WebUI.Controllers; 9 | using System.Web.Mvc; 10 | using MyShop.Core.ViewModels; 11 | using System.Security.Principal; 12 | 13 | namespace MyShop.WebUI.Tests.Controllers 14 | { 15 | [TestClass] 16 | public class BasketControllerTests 17 | { 18 | [TestMethod] 19 | public void CanAddBasketItem() 20 | { 21 | //setup 22 | IRepository baskets = new MockContext(); 23 | IRepository products = new MockContext(); 24 | IRepository orders = new MockContext(); 25 | IRepository customers = new MockContext(); 26 | 27 | var httpContext = new MockHttpContext(); 28 | 29 | 30 | IBasketService basketService = new BasketService(products, baskets); 31 | IOrderService orderService = new OrderService(orders); 32 | var controller = new BasketController(basketService, orderService, customers); 33 | controller.ControllerContext = new System.Web.Mvc.ControllerContext(httpContext, new System.Web.Routing.RouteData(), controller); 34 | 35 | //Act 36 | //basketService.AddToBasket(httpContext, "1"); 37 | controller.AddToBasket("1"); 38 | 39 | Basket basket = baskets.Collection().FirstOrDefault(); 40 | 41 | 42 | //Assert 43 | Assert.IsNotNull(basket); 44 | Assert.AreEqual(1, basket.BasketItems.Count); 45 | Assert.AreEqual("1", basket.BasketItems.ToList().FirstOrDefault().ProductId); 46 | } 47 | 48 | [TestMethod] 49 | public void CanGetSummaryViewModel() { 50 | IRepository baskets = new MockContext(); 51 | IRepository products = new MockContext(); 52 | IRepository orders = new MockContext(); 53 | IRepository customers = new MockContext(); 54 | 55 | products.Insert(new Product() { Id = "1", Price = 10.00m }); 56 | products.Insert(new Product() { Id = "2", Price = 5.00m }); 57 | 58 | Basket basket = new Basket(); 59 | basket.BasketItems.Add(new BasketItem() { ProductId = "1", Quanity = 2 }); 60 | basket.BasketItems.Add(new BasketItem() { ProductId = "2", Quanity = 1 }); 61 | baskets.Insert(basket); 62 | 63 | IBasketService basketService = new BasketService(products, baskets); 64 | IOrderService orderService = new OrderService(orders); 65 | var controller = new BasketController(basketService, orderService, customers); 66 | 67 | var httpContext = new MockHttpContext(); 68 | httpContext.Request.Cookies.Add(new System.Web.HttpCookie("eCommerceBasket") { Value = basket.Id }); 69 | controller.ControllerContext = new System.Web.Mvc.ControllerContext(httpContext, new System.Web.Routing.RouteData(), controller); 70 | 71 | 72 | var result = controller.BasketSummary() as PartialViewResult; 73 | var basketSummary = (BasketSummaryViewModel)result.ViewData.Model; 74 | 75 | Assert.AreEqual(3, basketSummary.BasketCount); 76 | Assert.AreEqual(25.00m, basketSummary.BasketTotal); 77 | 78 | 79 | } 80 | 81 | [TestMethod] 82 | public void CanCheckoutAndCreateOrder() { 83 | IRepository customers = new MockContext(); 84 | IRepository products = new MockContext(); 85 | products.Insert(new Product() { Id = "1", Price = 10.00m }); 86 | products.Insert(new Product() { Id = "2", Price = 5.00m }); 87 | 88 | IRepository baskets = new MockContext(); 89 | Basket basket = new Basket(); 90 | basket.BasketItems.Add(new BasketItem() { ProductId = "1", Quanity = 2, BasketId = basket.Id }); 91 | basket.BasketItems.Add(new BasketItem() { ProductId = "1", Quanity = 1, BasketId = basket.Id }); 92 | 93 | baskets.Insert(basket); 94 | 95 | IBasketService basketService = new BasketService(products, baskets); 96 | 97 | IRepository orders = new MockContext(); 98 | IOrderService orderService = new OrderService(orders); 99 | 100 | customers.Insert(new Customer() { Id = "1", Email = "brett.hargreaves@gmail.com", ZipCode = "90210" }); 101 | 102 | IPrincipal FakeUser = new GenericPrincipal(new GenericIdentity("brett.hargreaves@gmail.com", "Forms"), null); 103 | 104 | 105 | var controller = new BasketController(basketService, orderService, customers); 106 | var httpContext = new MockHttpContext(); 107 | httpContext.User = FakeUser; 108 | httpContext.Request.Cookies.Add(new System.Web.HttpCookie("eCommerceBasket") 109 | { 110 | Value = basket.Id 111 | }); 112 | 113 | controller.ControllerContext = new ControllerContext(httpContext, new System.Web.Routing.RouteData(), controller); 114 | 115 | //Act 116 | Order order = new Order(); 117 | controller.Checkout(order); 118 | 119 | //assert 120 | Assert.AreEqual(2, order.OrderItems.Count); 121 | Assert.AreEqual(0, basket.BasketItems.Count); 122 | 123 | Order orderInRep = orders.Find(order.Id); 124 | Assert.AreEqual(2, orderInRep.OrderItems.Count); 125 | 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI.Tests/Controllers/HomeControllerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using MyShop.WebUI.Controllers; 4 | using MyShop.Core.Contracts; 5 | using MyShop.Core.Models; 6 | using System.Web.Mvc; 7 | using MyShop.Core.ViewModels; 8 | using System.Linq; 9 | 10 | namespace MyShop.WebUI.Tests.Controllers 11 | { 12 | [TestClass] 13 | public class UnitTest1 14 | { 15 | [TestMethod] 16 | public void IndexPageDoesReturnProducts() 17 | { 18 | IRepository productContext = new Mocks.MockContext(); 19 | IRepository productCatgeoryContext = new Mocks.MockContext(); 20 | 21 | productContext.Insert(new Product()); 22 | 23 | HomeController controller = new HomeController(productContext, productCatgeoryContext); 24 | 25 | var result = controller.Index() as ViewResult; 26 | var viewModel = (ProductListViewModel)result.ViewData.Model; 27 | 28 | Assert.AreEqual(1, viewModel.Products.Count()); 29 | 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI.Tests/Mocks/MockContext.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace MyShop.WebUI.Tests.Mocks 10 | { 11 | public class MockContext : IRepository where T: BaseEntity 12 | { 13 | List items; 14 | string className; 15 | 16 | public MockContext() 17 | { 18 | items = new List(); 19 | } 20 | 21 | public void Commit() 22 | { 23 | return; 24 | } 25 | 26 | public void Insert(T t) 27 | { 28 | items.Add(t); 29 | } 30 | 31 | public void Update(T t) 32 | { 33 | T tToUpdate = items.Find(i => i.Id == t.Id); 34 | 35 | if (tToUpdate != null) 36 | { 37 | tToUpdate = t; 38 | } 39 | else 40 | { 41 | throw new Exception(className + " Not found"); 42 | } 43 | } 44 | 45 | public T Find(string Id) 46 | { 47 | T t = items.Find(i => i.Id == Id); 48 | if (t != null) 49 | { 50 | return t; 51 | } 52 | else 53 | { 54 | throw new Exception(className + " Not found"); 55 | } 56 | } 57 | 58 | public IQueryable Collection() 59 | { 60 | return items.AsQueryable(); 61 | } 62 | 63 | public void Delete(string Id) 64 | { 65 | T tToDelete = items.Find(i => i.Id == Id); 66 | 67 | if (tToDelete != null) 68 | { 69 | items.Remove(tToDelete); 70 | } 71 | else 72 | { 73 | throw new Exception(className + " Not found"); 74 | } 75 | } 76 | 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI.Tests/Mocks/MockHttpContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Principal; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Web; 8 | 9 | namespace MyShop.WebUI.Tests.Mocks 10 | { 11 | public class MockHttpContext : HttpContextBase 12 | { 13 | private MockRequest request; 14 | private MockResponse response; 15 | private HttpCookieCollection cookies; 16 | private IPrincipal FakeUser; 17 | 18 | public MockHttpContext() { 19 | cookies = new HttpCookieCollection(); 20 | this.request = new MockRequest(cookies); 21 | this.response = new MockResponse(cookies); 22 | } 23 | 24 | public override IPrincipal User { 25 | get { 26 | return this.FakeUser; 27 | } 28 | set { 29 | this.FakeUser = value; 30 | } 31 | 32 | } 33 | 34 | public override HttpRequestBase Request { 35 | get { 36 | return request; 37 | } 38 | } 39 | 40 | public override HttpResponseBase Response { 41 | get { 42 | return response; 43 | } 44 | } 45 | } 46 | 47 | public class MockResponse : HttpResponseBase { 48 | private readonly HttpCookieCollection cookies; 49 | 50 | public MockResponse(HttpCookieCollection cookies) { 51 | this.cookies = cookies; 52 | } 53 | 54 | public override HttpCookieCollection Cookies { 55 | get { 56 | return cookies; 57 | } 58 | } 59 | } 60 | 61 | public class MockRequest : HttpRequestBase 62 | { 63 | private readonly HttpCookieCollection cookies; 64 | 65 | public MockRequest(HttpCookieCollection cookies) 66 | { 67 | this.cookies = cookies; 68 | } 69 | 70 | public override HttpCookieCollection Cookies 71 | { 72 | get 73 | { 74 | return cookies; 75 | } 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MyShop.WebUI.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MyShop.WebUI.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fc730f30-3a37-4cb8-810b-be986ab7f298")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace MyShop.WebUI 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at https://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js", 24 | "~/Scripts/respond.js")); 25 | 26 | bundles.Add(new StyleBundle("~/Content/css").Include( 27 | "~/Content/bootstrap.css", 28 | "~/Content/site.css")); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace MyShop.WebUI 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/App_Start/IdentityConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Entity; 4 | using System.Linq; 5 | using System.Security.Claims; 6 | using System.Threading.Tasks; 7 | using System.Web; 8 | using Microsoft.AspNet.Identity; 9 | using Microsoft.AspNet.Identity.EntityFramework; 10 | using Microsoft.AspNet.Identity.Owin; 11 | using Microsoft.Owin; 12 | using Microsoft.Owin.Security; 13 | using MyShop.WebUI.Models; 14 | 15 | namespace MyShop.WebUI 16 | { 17 | public class EmailService : IIdentityMessageService 18 | { 19 | public Task SendAsync(IdentityMessage message) 20 | { 21 | // Plug in your email service here to send an email. 22 | return Task.FromResult(0); 23 | } 24 | } 25 | 26 | public class SmsService : IIdentityMessageService 27 | { 28 | public Task SendAsync(IdentityMessage message) 29 | { 30 | // Plug in your SMS service here to send a text message. 31 | return Task.FromResult(0); 32 | } 33 | } 34 | 35 | // Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application. 36 | public class ApplicationUserManager : UserManager 37 | { 38 | public ApplicationUserManager(IUserStore store) 39 | : base(store) 40 | { 41 | } 42 | 43 | public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) 44 | { 45 | var manager = new ApplicationUserManager(new UserStore(context.Get())); 46 | // Configure validation logic for usernames 47 | manager.UserValidator = new UserValidator(manager) 48 | { 49 | AllowOnlyAlphanumericUserNames = false, 50 | RequireUniqueEmail = true 51 | }; 52 | 53 | // Configure validation logic for passwords 54 | manager.PasswordValidator = new PasswordValidator 55 | { 56 | RequiredLength = 6, 57 | RequireNonLetterOrDigit = true, 58 | RequireDigit = true, 59 | RequireLowercase = true, 60 | RequireUppercase = true, 61 | }; 62 | 63 | // Configure user lockout defaults 64 | manager.UserLockoutEnabledByDefault = true; 65 | manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); 66 | manager.MaxFailedAccessAttemptsBeforeLockout = 5; 67 | 68 | // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user 69 | // You can write your own provider and plug it in here. 70 | manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider 71 | { 72 | MessageFormat = "Your security code is {0}" 73 | }); 74 | manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider 75 | { 76 | Subject = "Security Code", 77 | BodyFormat = "Your security code is {0}" 78 | }); 79 | manager.EmailService = new EmailService(); 80 | manager.SmsService = new SmsService(); 81 | var dataProtectionProvider = options.DataProtectionProvider; 82 | if (dataProtectionProvider != null) 83 | { 84 | manager.UserTokenProvider = 85 | new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); 86 | } 87 | return manager; 88 | } 89 | } 90 | 91 | // Configure the application sign-in manager which is used in this application. 92 | public class ApplicationSignInManager : SignInManager 93 | { 94 | public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) 95 | : base(userManager, authenticationManager) 96 | { 97 | } 98 | 99 | public override Task CreateUserIdentityAsync(ApplicationUser user) 100 | { 101 | return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); 102 | } 103 | 104 | public static ApplicationSignInManager Create(IdentityFactoryOptions options, IOwinContext context) 105 | { 106 | return new ApplicationSignInManager(context.GetUserManager(), context.Authentication); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace MyShop.WebUI 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/App_Start/Startup.Auth.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNet.Identity; 3 | using Microsoft.AspNet.Identity.Owin; 4 | using Microsoft.Owin; 5 | using Microsoft.Owin.Security.Cookies; 6 | using Microsoft.Owin.Security.Google; 7 | using Owin; 8 | using MyShop.WebUI.Models; 9 | 10 | namespace MyShop.WebUI 11 | { 12 | public partial class Startup 13 | { 14 | // For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864 15 | public void ConfigureAuth(IAppBuilder app) 16 | { 17 | // Configure the db context, user manager and signin manager to use a single instance per request 18 | app.CreatePerOwinContext(ApplicationDbContext.Create); 19 | app.CreatePerOwinContext(ApplicationUserManager.Create); 20 | app.CreatePerOwinContext(ApplicationSignInManager.Create); 21 | 22 | // Enable the application to use a cookie to store information for the signed in user 23 | // and to use a cookie to temporarily store information about a user logging in with a third party login provider 24 | // Configure the sign in cookie 25 | app.UseCookieAuthentication(new CookieAuthenticationOptions 26 | { 27 | AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 28 | LoginPath = new PathString("/Account/Login"), 29 | Provider = new CookieAuthenticationProvider 30 | { 31 | // Enables the application to validate the security stamp when the user logs in. 32 | // This is a security feature which is used when you change a password or add an external login to your account. 33 | OnValidateIdentity = SecurityStampValidator.OnValidateIdentity( 34 | validateInterval: TimeSpan.FromMinutes(30), 35 | regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) 36 | } 37 | }); 38 | app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 39 | 40 | // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process. 41 | app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)); 42 | 43 | // Enables the application to remember the second login verification factor such as phone or email. 44 | // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from. 45 | // This is similar to the RememberMe option when you log in. 46 | app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie); 47 | 48 | // Uncomment the following lines to enable logging in with third party login providers 49 | //app.UseMicrosoftAccountAuthentication( 50 | // clientId: "", 51 | // clientSecret: ""); 52 | 53 | //app.UseTwitterAuthentication( 54 | // consumerKey: "", 55 | // consumerSecret: ""); 56 | 57 | //app.UseFacebookAuthentication( 58 | // appId: "", 59 | // appSecret: ""); 60 | 61 | //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() 62 | //{ 63 | // ClientId = "", 64 | // ClientSecret = "" 65 | //}); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/App_Start/UnityConfig.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using MyShop.DataAccess.InMemory; 4 | using MyShop.DataAccess.SQL; 5 | using MyShop.Services; 6 | using System; 7 | 8 | using Unity; 9 | 10 | namespace MyShop.WebUI 11 | { 12 | /// 13 | /// Specifies the Unity configuration for the main container. 14 | /// 15 | public static class UnityConfig 16 | { 17 | #region Unity Container 18 | private static Lazy container = 19 | new Lazy(() => 20 | { 21 | var container = new UnityContainer(); 22 | RegisterTypes(container); 23 | return container; 24 | }); 25 | 26 | /// 27 | /// Configured Unity Container. 28 | /// 29 | public static IUnityContainer Container => container.Value; 30 | #endregion 31 | 32 | /// 33 | /// Registers the type mappings with the Unity container. 34 | /// 35 | /// The unity container to configure. 36 | /// 37 | /// There is no need to register concrete types such as controllers or 38 | /// API controllers (unless you want to change the defaults), as Unity 39 | /// allows resolving a concrete type even if it was not previously 40 | /// registered. 41 | /// 42 | public static void RegisterTypes(IUnityContainer container) 43 | { 44 | // NOTE: To load from web.config uncomment the line below. 45 | // Make sure to add a Unity.Configuration to the using statements. 46 | // container.LoadConfiguration(); 47 | 48 | // TODO: Register your type's mappings here. 49 | // container.RegisterType(); 50 | container.RegisterType, SQLRepository>(); 51 | container.RegisterType, SQLRepository>(); 52 | container.RegisterType, SQLRepository>(); 53 | container.RegisterType, SQLRepository>(); 54 | container.RegisterType, SQLRepository>(); 55 | container.RegisterType, SQLRepository>(); 56 | 57 | container.RegisterType(); 58 | container.RegisterType(); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/App_Start/UnityMvcActivator.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Web.Mvc; 3 | 4 | using Unity.AspNet.Mvc; 5 | 6 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyShop.WebUI.UnityMvcActivator), nameof(MyShop.WebUI.UnityMvcActivator.Start))] 7 | [assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(MyShop.WebUI.UnityMvcActivator), nameof(MyShop.WebUI.UnityMvcActivator.Shutdown))] 8 | 9 | namespace MyShop.WebUI 10 | { 11 | /// 12 | /// Provides the bootstrapping for integrating Unity with ASP.NET MVC. 13 | /// 14 | public static class UnityMvcActivator 15 | { 16 | /// 17 | /// Integrates Unity when the application starts. 18 | /// 19 | public static void Start() 20 | { 21 | FilterProviders.Providers.Remove(FilterProviders.Providers.OfType().First()); 22 | FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container)); 23 | 24 | DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container)); 25 | 26 | // TODO: Uncomment if you want to use PerRequestLifetimeManager 27 | // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule)); 28 | } 29 | 30 | /// 31 | /// Disposes the Unity container when the application is shut down. 32 | /// 33 | public static void Shutdown() 34 | { 35 | UnityConfig.Container.Dispose(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Content/ProductImages/720780c9-f6ca-4ebc-8647-4164dea5a3ab.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/completecoder/MyShop/25e6098b113dffcc545f4fc493e01f7d34dd31f7/MyShop/MyShop.WebUI/Content/ProductImages/720780c9-f6ca-4ebc-8647-4164dea5a3ab.jpg -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Content/ProductImages/7acd2efb-4ac1-457e-b19d-079b430e25f1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/completecoder/MyShop/25e6098b113dffcc545f4fc493e01f7d34dd31f7/MyShop/MyShop.WebUI/Content/ProductImages/7acd2efb-4ac1-457e-b19d-079b430e25f1.jpg -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Override the default bootstrap behavior where horizontal description lists 13 | will truncate terms that are too long to fit in the left column 14 | */ 15 | .dl-horizontal dt { 16 | white-space: normal; 17 | } 18 | 19 | /* Set width on the form input elements since they're 100% wide by default */ 20 | input, 21 | select, 22 | textarea { 23 | max-width: 280px; 24 | } 25 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Controllers/AdminController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace MyShop.WebUI.Controllers 8 | { 9 | [Authorize(Roles ="Admin")] 10 | public class AdminController : Controller 11 | { 12 | // GET: Admin 13 | public ActionResult Index() 14 | { 15 | return View(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Controllers/BasketController.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Web; 7 | using System.Web.Mvc; 8 | 9 | namespace MyShop.WebUI.Controllers 10 | { 11 | public class BasketController : Controller 12 | { 13 | IRepository customers; 14 | IBasketService basketService; 15 | IOrderService orderService; 16 | 17 | public BasketController(IBasketService BasketService, IOrderService OrderService, IRepository Customers) { 18 | this.basketService = BasketService; 19 | this.orderService = OrderService; 20 | this.customers = Customers; 21 | } 22 | // GET: Basket2 23 | public ActionResult Index() 24 | { 25 | var model = basketService.GetBasketItems(this.HttpContext); 26 | return View(model); 27 | } 28 | 29 | public ActionResult AddToBasket(string Id) 30 | { 31 | basketService.AddToBasket(this.HttpContext, Id); 32 | 33 | return RedirectToAction("Index"); 34 | } 35 | 36 | public ActionResult RemoveFromBasket(string Id) 37 | { 38 | basketService.RemoveFromBasket(this.HttpContext, Id); 39 | 40 | return RedirectToAction("Index"); 41 | } 42 | 43 | public PartialViewResult BasketSummary() { 44 | var basketSummary = basketService.GetBasketSummary(this.HttpContext); 45 | 46 | return PartialView(basketSummary); 47 | } 48 | 49 | [Authorize] 50 | public ActionResult Checkout() { 51 | Customer customer = customers.Collection().FirstOrDefault(c => c.Email == User.Identity.Name); 52 | 53 | if (customer != null) 54 | { 55 | Order order = new Order() 56 | { 57 | Email = customer.Email, 58 | City = customer.City, 59 | State = customer.State, 60 | Street = customer.Street, 61 | FirstName = customer.FirstName, 62 | Surname = customer.LastName, 63 | ZipCode = customer.ZipCode 64 | }; 65 | 66 | return View(order); 67 | } 68 | else { 69 | return RedirectToAction("Error"); 70 | } 71 | 72 | } 73 | 74 | [HttpPost] 75 | [Authorize] 76 | public ActionResult Checkout(Order order) { 77 | 78 | var basketItems = basketService.GetBasketItems(this.HttpContext); 79 | order.OrderStatus = "Order Created"; 80 | order.Email = User.Identity.Name; 81 | 82 | //process payment 83 | 84 | order.OrderStatus = "Payment Processed"; 85 | orderService.CreateOrder(order, basketItems); 86 | basketService.ClearBasket(this.HttpContext); 87 | 88 | return RedirectToAction("Thankyou", new { OrderId = order.Id }); 89 | } 90 | 91 | public ActionResult ThankYou(string OrderId) { 92 | ViewBag.OrderId = OrderId; 93 | return View(); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using MyShop.Core.ViewModels; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Web; 8 | using System.Web.Mvc; 9 | 10 | namespace MyShop.WebUI.Controllers 11 | { 12 | public class HomeController : Controller 13 | { 14 | IRepository context; 15 | IRepository productCategories; 16 | 17 | public HomeController(IRepository productContext, IRepository productCategoryContext) 18 | { 19 | context = productContext; 20 | productCategories = productCategoryContext; 21 | } 22 | 23 | public ActionResult Index(string Category=null) 24 | { 25 | List products; 26 | List categories = productCategories.Collection().ToList(); 27 | 28 | if (Category == null) 29 | { 30 | products = context.Collection().ToList(); 31 | } 32 | else { 33 | products = context.Collection().Where(p => p.Category == Category).ToList(); 34 | } 35 | 36 | ProductListViewModel model = new ProductListViewModel(); 37 | model.Products = products; 38 | model.ProductCategories = categories; 39 | 40 | 41 | return View(model); 42 | } 43 | 44 | public ActionResult Details(string Id) { 45 | Product product = context.Find(Id); 46 | if (product == null) 47 | { 48 | return HttpNotFound(); 49 | } 50 | else { 51 | return View(product); 52 | } 53 | } 54 | 55 | public ActionResult About() 56 | { 57 | ViewBag.Message = "Your application description page."; 58 | 59 | return View(); 60 | } 61 | 62 | public ActionResult Contact() 63 | { 64 | ViewBag.Message = "Your contact page."; 65 | 66 | return View(); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Controllers/OrderManagerController.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Web; 7 | using System.Web.Mvc; 8 | 9 | namespace MyShop.WebUI.Controllers 10 | { 11 | [Authorize(Roles = "Admin")] 12 | public class OrderManagerController : Controller 13 | { 14 | IOrderService orderService; 15 | 16 | public OrderManagerController(IOrderService OrderService) { 17 | this.orderService = OrderService; 18 | } 19 | // GET: OrderManager 20 | public ActionResult Index() 21 | { 22 | List orders = orderService.GetOrderList(); 23 | 24 | return View(orders); 25 | } 26 | 27 | public ActionResult UpdateOrder(string Id) { 28 | ViewBag.StatusList = new List() { 29 | "Order Created", 30 | "Payment Processed", 31 | "Order Shipped", 32 | "Order Complete" 33 | }; 34 | Order order = orderService.GetOrder(Id); 35 | return View(order); 36 | } 37 | 38 | [HttpPost] 39 | public ActionResult UpdateOrder(Order updatedOrder, string Id) { 40 | Order order = orderService.GetOrder(Id); 41 | 42 | order.OrderStatus = updatedOrder.OrderStatus; 43 | orderService.UpdateOrder(order); 44 | 45 | return RedirectToAction("Index"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Controllers/ProductCategoryManagerController.cs: -------------------------------------------------------------------------------- 1 | using MyShop.Core.Contracts; 2 | using MyShop.Core.Models; 3 | using MyShop.DataAccess.InMemory; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Web; 8 | using System.Web.Mvc; 9 | 10 | namespace MyShop.WebUI.Controllers 11 | { 12 | [Authorize(Roles = "Admin")] 13 | public class ProductCategoryManagerController : Controller 14 | { 15 | IRepository context; 16 | 17 | public ProductCategoryManagerController(IRepository context) 18 | { 19 | this.context = context; 20 | } 21 | // GET: ProductManager 22 | public ActionResult Index() 23 | { 24 | List productCategories = context.Collection().ToList(); 25 | return View(productCategories); 26 | } 27 | 28 | public ActionResult Create() 29 | { 30 | ProductCategory productCategory = new ProductCategory(); 31 | return View(productCategory); 32 | } 33 | 34 | [HttpPost] 35 | public ActionResult Create(ProductCategory productCategory) 36 | { 37 | if (!ModelState.IsValid) 38 | { 39 | return View(productCategory); 40 | } 41 | else 42 | { 43 | context.Insert(productCategory); 44 | context.Commit(); 45 | 46 | return RedirectToAction("Index"); 47 | } 48 | 49 | } 50 | 51 | public ActionResult Edit(string Id) 52 | { 53 | ProductCategory productCategory = context.Find(Id); 54 | if (productCategory == null) 55 | { 56 | return HttpNotFound(); 57 | } 58 | else 59 | { 60 | return View(productCategory); 61 | } 62 | } 63 | 64 | [HttpPost] 65 | public ActionResult Edit(ProductCategory product, string Id) 66 | { 67 | ProductCategory productCategoryToEdit = context.Find(Id); 68 | 69 | if (productCategoryToEdit == null) 70 | { 71 | return HttpNotFound(); 72 | } 73 | else 74 | { 75 | if (!ModelState.IsValid) 76 | { 77 | return View(product); 78 | } 79 | 80 | productCategoryToEdit.Category = product.Category; 81 | 82 | context.Commit(); 83 | 84 | return RedirectToAction("Index"); 85 | } 86 | } 87 | 88 | public ActionResult Delete(string Id) 89 | { 90 | ProductCategory productCategoryToDelete = context.Find(Id); 91 | 92 | if (productCategoryToDelete == null) 93 | { 94 | return HttpNotFound(); 95 | } 96 | else 97 | { 98 | return View(productCategoryToDelete); 99 | } 100 | } 101 | 102 | [HttpPost] 103 | [ActionName("Delete")] 104 | public ActionResult ConfirmDelete(string Id) 105 | { 106 | ProductCategory productCategoryToDelete = context.Find(Id); 107 | 108 | if (productCategoryToDelete == null) 109 | { 110 | return HttpNotFound(); 111 | } 112 | else 113 | { 114 | context.Delete(Id); 115 | context.Commit(); 116 | return RedirectToAction("Index"); 117 | } 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Controllers/ProductManagerController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using MyShop.Core.Models; 7 | using MyShop.DataAccess.InMemory; 8 | using MyShop.Core.ViewModels; 9 | using MyShop.Core.Contracts; 10 | using System.IO; 11 | 12 | namespace MyShop.WebUI.Controllers 13 | { 14 | [Authorize(Roles = "Admin")] 15 | public class ProductManagerController : Controller 16 | { 17 | IRepository context; 18 | IRepository productCategories; 19 | 20 | public ProductManagerController(IRepository productContext, IRepository productCategoryContext) { 21 | context = productContext; 22 | productCategories = productCategoryContext; 23 | } 24 | // GET: ProductManager 25 | public ActionResult Index() 26 | { 27 | List products = context.Collection().ToList(); 28 | return View(products); 29 | } 30 | 31 | public ActionResult Create() { 32 | ProductManagerViewModel viewModel = new ProductManagerViewModel(); 33 | 34 | viewModel.Product = new Product(); 35 | viewModel.ProductCategories = productCategories.Collection(); 36 | return View(viewModel); 37 | } 38 | 39 | [HttpPost] 40 | public ActionResult Create(Product product, HttpPostedFileBase file) { 41 | if (!ModelState.IsValid) 42 | { 43 | return View(product); 44 | } 45 | else { 46 | 47 | if (file != null) { 48 | product.Image = product.Id + Path.GetExtension(file.FileName); 49 | file.SaveAs(Server.MapPath("//Content//ProductImages//") + product.Image); 50 | } 51 | 52 | context.Insert(product); 53 | context.Commit(); 54 | 55 | return RedirectToAction("Index"); 56 | } 57 | 58 | } 59 | 60 | public ActionResult Edit(string Id) { 61 | Product product = context.Find(Id); 62 | if (product == null) 63 | { 64 | return HttpNotFound(); 65 | } 66 | else { 67 | ProductManagerViewModel viewModel = new ProductManagerViewModel(); 68 | viewModel.Product = product; 69 | viewModel.ProductCategories = productCategories.Collection(); 70 | 71 | return View(viewModel); 72 | } 73 | } 74 | 75 | [HttpPost] 76 | public ActionResult Edit(Product product, string Id, HttpPostedFileBase file) { 77 | Product productToEdit = context.Find(Id); 78 | 79 | if (productToEdit == null) 80 | { 81 | return HttpNotFound(); 82 | } 83 | else 84 | { 85 | if (!ModelState.IsValid) { 86 | return View(product); 87 | } 88 | 89 | if (file != null) { 90 | productToEdit.Image = product.Id + Path.GetExtension(file.FileName); 91 | file.SaveAs(Server.MapPath("//Content//ProductImages//") + productToEdit.Image); 92 | } 93 | 94 | productToEdit.Category = product.Category; 95 | productToEdit.Description = product.Description; 96 | productToEdit.Name = product.Name; 97 | productToEdit.Price = product.Price; 98 | 99 | context.Commit(); 100 | 101 | return RedirectToAction("Index"); 102 | } 103 | } 104 | 105 | public ActionResult Delete(string Id) 106 | { 107 | Product productToDelete = context.Find(Id); 108 | 109 | if (productToDelete == null) 110 | { 111 | return HttpNotFound(); 112 | } 113 | else 114 | { 115 | return View(productToDelete); 116 | } 117 | } 118 | 119 | [HttpPost] 120 | [ActionName("Delete")] 121 | public ActionResult ConfirmDelete(string Id) { 122 | Product productToDelete = context.Find(Id); 123 | 124 | if (productToDelete == null) 125 | { 126 | return HttpNotFound(); 127 | } 128 | else 129 | { 130 | context.Delete(Id); 131 | context.Commit(); 132 | return RedirectToAction("Index"); 133 | } 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="MyShop.WebUI.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | 9 | namespace MyShop.WebUI 10 | { 11 | public class MvcApplication : System.Web.HttpApplication 12 | { 13 | protected void Application_Start() 14 | { 15 | AreaRegistration.RegisterAllAreas(); 16 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 17 | RouteConfig.RegisterRoutes(RouteTable.Routes); 18 | BundleConfig.RegisterBundles(BundleTable.Bundles); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Models/AccountViewModels.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace MyShop.WebUI.Models 5 | { 6 | public class ExternalLoginConfirmationViewModel 7 | { 8 | [Required] 9 | [Display(Name = "Email")] 10 | public string Email { get; set; } 11 | } 12 | 13 | public class ExternalLoginListViewModel 14 | { 15 | public string ReturnUrl { get; set; } 16 | } 17 | 18 | public class SendCodeViewModel 19 | { 20 | public string SelectedProvider { get; set; } 21 | public ICollection Providers { get; set; } 22 | public string ReturnUrl { get; set; } 23 | public bool RememberMe { get; set; } 24 | } 25 | 26 | public class VerifyCodeViewModel 27 | { 28 | [Required] 29 | public string Provider { get; set; } 30 | 31 | [Required] 32 | [Display(Name = "Code")] 33 | public string Code { get; set; } 34 | public string ReturnUrl { get; set; } 35 | 36 | [Display(Name = "Remember this browser?")] 37 | public bool RememberBrowser { get; set; } 38 | 39 | public bool RememberMe { get; set; } 40 | } 41 | 42 | public class ForgotViewModel 43 | { 44 | [Required] 45 | [Display(Name = "Email")] 46 | public string Email { get; set; } 47 | } 48 | 49 | public class LoginViewModel 50 | { 51 | [Required] 52 | [Display(Name = "Email")] 53 | [EmailAddress] 54 | public string Email { get; set; } 55 | 56 | [Required] 57 | [DataType(DataType.Password)] 58 | [Display(Name = "Password")] 59 | public string Password { get; set; } 60 | 61 | [Display(Name = "Remember me?")] 62 | public bool RememberMe { get; set; } 63 | } 64 | 65 | public class RegisterViewModel 66 | { 67 | [Required] 68 | [EmailAddress] 69 | [Display(Name = "Email")] 70 | public string Email { get; set; } 71 | 72 | [Required] 73 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 74 | [DataType(DataType.Password)] 75 | [Display(Name = "Password")] 76 | public string Password { get; set; } 77 | 78 | [DataType(DataType.Password)] 79 | [Display(Name = "Confirm password")] 80 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 81 | public string ConfirmPassword { get; set; } 82 | 83 | [Required] 84 | public string FirstName { get; set; } 85 | [Required] 86 | public string LastName { get; set; } 87 | [Required] 88 | public string Street { get; set; } 89 | [Required] 90 | public string City { get; set; } 91 | public string State { get; set; } 92 | [Required] 93 | public string ZipCode { get; set; } 94 | } 95 | 96 | public class ResetPasswordViewModel 97 | { 98 | [Required] 99 | [EmailAddress] 100 | [Display(Name = "Email")] 101 | public string Email { get; set; } 102 | 103 | [Required] 104 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 105 | [DataType(DataType.Password)] 106 | [Display(Name = "Password")] 107 | public string Password { get; set; } 108 | 109 | [DataType(DataType.Password)] 110 | [Display(Name = "Confirm password")] 111 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 112 | public string ConfirmPassword { get; set; } 113 | 114 | public string Code { get; set; } 115 | } 116 | 117 | public class ForgotPasswordViewModel 118 | { 119 | [Required] 120 | [EmailAddress] 121 | [Display(Name = "Email")] 122 | public string Email { get; set; } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Models/IdentityModels.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Entity; 2 | using System.Security.Claims; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNet.Identity; 5 | using Microsoft.AspNet.Identity.EntityFramework; 6 | 7 | namespace MyShop.WebUI.Models 8 | { 9 | // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit https://go.microsoft.com/fwlink/?LinkID=317594 to learn more. 10 | public class ApplicationUser : IdentityUser 11 | { 12 | public async Task GenerateUserIdentityAsync(UserManager manager) 13 | { 14 | // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 15 | var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 16 | // Add custom user claims here 17 | return userIdentity; 18 | } 19 | } 20 | 21 | public class ApplicationDbContext : IdentityDbContext 22 | { 23 | public ApplicationDbContext() 24 | : base("DefaultConnection", throwIfV1Schema: false) 25 | { 26 | } 27 | 28 | public static ApplicationDbContext Create() 29 | { 30 | return new ApplicationDbContext(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Models/ManageViewModels.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using Microsoft.AspNet.Identity; 4 | using Microsoft.Owin.Security; 5 | 6 | namespace MyShop.WebUI.Models 7 | { 8 | public class IndexViewModel 9 | { 10 | public bool HasPassword { get; set; } 11 | public IList Logins { get; set; } 12 | public string PhoneNumber { get; set; } 13 | public bool TwoFactor { get; set; } 14 | public bool BrowserRemembered { get; set; } 15 | } 16 | 17 | public class ManageLoginsViewModel 18 | { 19 | public IList CurrentLogins { get; set; } 20 | public IList OtherLogins { get; set; } 21 | } 22 | 23 | public class FactorViewModel 24 | { 25 | public string Purpose { get; set; } 26 | } 27 | 28 | public class SetPasswordViewModel 29 | { 30 | [Required] 31 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 32 | [DataType(DataType.Password)] 33 | [Display(Name = "New password")] 34 | public string NewPassword { get; set; } 35 | 36 | [DataType(DataType.Password)] 37 | [Display(Name = "Confirm new password")] 38 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 39 | public string ConfirmPassword { get; set; } 40 | } 41 | 42 | public class ChangePasswordViewModel 43 | { 44 | [Required] 45 | [DataType(DataType.Password)] 46 | [Display(Name = "Current password")] 47 | public string OldPassword { get; set; } 48 | 49 | [Required] 50 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 51 | [DataType(DataType.Password)] 52 | [Display(Name = "New password")] 53 | public string NewPassword { get; set; } 54 | 55 | [DataType(DataType.Password)] 56 | [Display(Name = "Confirm new password")] 57 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 58 | public string ConfirmPassword { get; set; } 59 | } 60 | 61 | public class AddPhoneNumberViewModel 62 | { 63 | [Required] 64 | [Phone] 65 | [Display(Name = "Phone Number")] 66 | public string Number { get; set; } 67 | } 68 | 69 | public class VerifyPhoneNumberViewModel 70 | { 71 | [Required] 72 | [Display(Name = "Code")] 73 | public string Code { get; set; } 74 | 75 | [Required] 76 | [Phone] 77 | [Display(Name = "Phone Number")] 78 | public string PhoneNumber { get; set; } 79 | } 80 | 81 | public class ConfigureTwoFactorViewModel 82 | { 83 | public string SelectedProvider { get; set; } 84 | public ICollection Providers { get; set; } 85 | } 86 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MyShop.WebUI")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MyShop.WebUI")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5d8ad84b-30ab-4fe7-8f95-2a1058797260")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Scripts/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /* 16 | ** Unobtrusive validation support library for jQuery and jQuery Validate 17 | ** Copyright (C) Microsoft Corporation. All rights reserved. 18 | */ 19 | (function(a){var d=a.validator,b,e="unobtrusiveValidation";function c(a,b,c){a.rules[b]=c;if(a.message)a.messages[b]=a.message}function j(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function f(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function h(a){return a.substr(0,a.lastIndexOf(".")+1)}function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);return a}function m(c,e){var b=a(this).find("[data-valmsg-for='"+f(e[0].name)+"']"),d=b.attr("data-valmsg-replace"),g=d?a.parseJSON(d)!==false:null;b.removeClass("field-validation-valid").addClass("field-validation-error");c.data("unobtrusiveContainer",b);if(g){b.empty();c.removeClass("input-validation-error").appendTo(b)}else c.hide()}function l(e,d){var c=a(this).find("[data-valmsg-summary=true]"),b=c.find("ul");if(b&&b.length&&d.errorList.length){b.empty();c.addClass("validation-summary-errors").removeClass("validation-summary-valid");a.each(d.errorList,function(){a("
  • ").html(this.message).appendTo(b)})}}function k(d){var b=d.data("unobtrusiveContainer"),c=b.attr("data-valmsg-replace"),e=c?a.parseJSON(c):null;if(b){b.addClass("field-validation-valid").removeClass("field-validation-error");d.removeData("unobtrusiveContainer");e&&b.empty()}}function n(){var b=a(this),c="__jquery_unobtrusive_validation_form_reset";if(b.data(c))return;b.data(c,true);try{b.data("validator").resetForm()}finally{b.removeData(c)}b.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors");b.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}function i(b){var c=a(b),f=c.data(e),i=a.proxy(n,b),g=d.unobtrusive.options||{},h=function(e,d){var c=g[e];c&&a.isFunction(c)&&c.apply(b,d)};if(!f){f={options:{errorClass:g.errorClass||"input-validation-error",errorElement:g.errorElement||"span",errorPlacement:function(){m.apply(b,arguments);h("errorPlacement",arguments)},invalidHandler:function(){l.apply(b,arguments);h("invalidHandler",arguments)},messages:{},rules:{},success:function(){k.apply(b,arguments);h("success",arguments)}},attachValidation:function(){c.off("reset."+e,i).on("reset."+e,i).validate(this.options)},validate:function(){c.validate();return c.valid()}};c.data(e,f)}return f}d.unobtrusive={adapters:[],parseElement:function(b,h){var d=a(b),f=d.parents("form")[0],c,e,g;if(!f)return;c=i(f);c.options.rules[b.name]=e={};c.options.messages[b.name]=g={};a.each(this.adapters,function(){var c="data-val-"+this.name,i=d.attr(c),h={};if(i!==undefined){c+="-";a.each(this.params,function(){h[this]=d.attr(c+this)});this.adapt({element:b,form:f,message:i,params:h,rules:e,messages:g})}});a.extend(e,{__dummy__:true});!h&&c.attachValidation()},parse:function(c){var b=a(c),e=b.parents().addBack().filter("form").add(b.find("form")).has("[data-val=true]");b.find("[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});e.each(function(){var a=i(this);a&&a.attachValidation()})}};b=d.unobtrusive.adapters;b.add=function(c,a,b){if(!b){b=a;a=[]}this.push({name:c,params:a,adapt:b});return this};b.addBool=function(a,b){return this.add(a,function(d){c(d,b||a,true)})};b.addMinMax=function(e,g,f,a,d,b){return this.add(e,[d||"min",b||"max"],function(b){var e=b.params.min,d=b.params.max;if(e&&d)c(b,a,[e,d]);else if(e)c(b,g,e);else d&&c(b,f,d)})};b.addSingleVal=function(a,b,d){return this.add(a,[b||"val"],function(e){c(e,d||a,e.params[b])})};d.addMethod("__dummy__",function(){return true});d.addMethod("regex",function(b,c,d){var a;if(this.optional(c))return true;a=(new RegExp(d)).exec(b);return a&&a.index===0&&a[0].length===b.length});d.addMethod("nonalphamin",function(c,d,b){var a;if(b){a=c.match(/\W/g);a=a&&a.length>=b}return a});if(d.methods.extension){b.addSingleVal("accept","mimtype");b.addSingleVal("extension","extension")}else b.addSingleVal("extension","extension","accept");b.addSingleVal("regex","pattern");b.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");b.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range");b.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength");b.add("equalto",["other"],function(b){var i=h(b.element.name),j=b.params.other,d=g(j,i),e=a(b.form).find(":input").filter("[name='"+f(d)+"']")[0];c(b,"equalTo",e)});b.add("required",function(a){(a.element.tagName.toUpperCase()!=="INPUT"||a.element.type.toUpperCase()!=="CHECKBOX")&&c(a,"required",true)});b.add("remote",["url","type","additionalfields"],function(b){var d={url:b.params.url,type:b.params.type||"GET",data:{}},e=h(b.element.name);a.each(j(b.params.additionalfields||b.element.name),function(i,h){var c=g(h,e);d.data[c]=function(){var d=a(b.form).find(":input").filter("[name='"+f(c)+"']");return d.is(":checkbox")?d.filter(":checked").val()||d.filter(":hidden").val()||"":d.is(":radio")?d.filter(":checked").val()||"":d.val()}});c(b,"remote",d)});b.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&c(a,"minlength",a.params.min);a.params.nonalphamin&&c(a,"nonalphamin",a.params.nonalphamin);a.params.regex&&c(a,"regex",a.params.regex)});a(function(){d.unobtrusive.parse(document)})})(jQuery); -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Scripts/respond.matchmedia.addListener.min.js: -------------------------------------------------------------------------------- 1 | /*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl 2 | * Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT 3 | * */ 4 | 5 | !function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";if(a.matchMedia&&a.matchMedia("all").addListener)return!1;var b=a.matchMedia,c=b("only all").matches,d=!1,e=0,f=[],g=function(){a.clearTimeout(e),e=a.setTimeout(function(){for(var c=0,d=f.length;d>c;c++){var e=f[c].mql,g=f[c].listeners||[],h=b(e.media).matches;if(h!==e.matches){e.matches=h;for(var i=0,j=g.length;j>i;i++)g[i].call(a,e)}}},30)};a.matchMedia=function(e){var h=b(e),i=[],j=0;return h.addListener=function(b){c&&(d||(d=!0,a.addEventListener("resize",g,!0)),0===j&&(j=f.push({mql:h,listeners:i})),i.push(b))},h.removeListener=function(a){for(var b=0,c=i.length;c>b;b++)i[b]===a&&i.splice(b,1)},h}}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b #mq-test-1 { width: 42px; }',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b@ViewBag.Title. 6 |
    7 |

    8 | Thank you for confirming your email. Please @Html.ActionLink("Click here to Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" }) 9 |

    10 |
    11 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/ExternalLoginConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.ExternalLoginConfirmationViewModel 2 | @{ 3 | ViewBag.Title = "Register"; 4 | } 5 |

    @ViewBag.Title.

    6 |

    Associate your @ViewBag.LoginProvider account.

    7 | 8 | @using (Html.BeginForm("ExternalLoginConfirmation", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 | 12 |

    Association Form

    13 |
    14 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 15 |

    16 | You've successfully authenticated with @ViewBag.LoginProvider. 17 | Please enter a user name for this site below and click the Register button to finish 18 | logging in. 19 |

    20 |
    21 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 22 |
    23 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 24 | @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" }) 25 |
    26 |
    27 |
    28 |
    29 | 30 |
    31 |
    32 | } 33 | 34 | @section Scripts { 35 | @Scripts.Render("~/bundles/jqueryval") 36 | } 37 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/ExternalLoginFailure.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Login Failure"; 3 | } 4 | 5 |
    6 |

    @ViewBag.Title.

    7 |

    Unsuccessful login with service.

    8 |
    9 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.ForgotPasswordViewModel 2 | @{ 3 | ViewBag.Title = "Forgot your password?"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 | @using (Html.BeginForm("ForgotPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

    Enter your email.

    12 |
    13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 |
    15 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 16 |
    17 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 18 |
    19 |
    20 |
    21 |
    22 | 23 |
    24 |
    25 | } 26 | 27 | @section Scripts { 28 | @Scripts.Render("~/bundles/jqueryval") 29 | } 30 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/ForgotPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Forgot Password Confirmation"; 3 | } 4 | 5 |
    6 |

    @ViewBag.Title.

    7 |
    8 |
    9 |

    10 | Please check your email to reset your password. 11 |

    12 |
    13 | 14 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using MyShop.WebUI.Models 2 | @model LoginViewModel 3 | @{ 4 | ViewBag.Title = "Log in"; 5 | } 6 | 7 |

    @ViewBag.Title.

    8 |
    9 |
    10 |
    11 | @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 12 | { 13 | @Html.AntiForgeryToken() 14 |

    Use a local account to log in.

    15 |
    16 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 17 |
    18 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 19 |
    20 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 21 | @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" }) 22 |
    23 |
    24 |
    25 | @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) 26 |
    27 | @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 28 | @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" }) 29 |
    30 |
    31 |
    32 |
    33 |
    34 | @Html.CheckBoxFor(m => m.RememberMe) 35 | @Html.LabelFor(m => m.RememberMe) 36 |
    37 |
    38 |
    39 |
    40 |
    41 | 42 |
    43 |
    44 |

    45 | @Html.ActionLink("Register as a new user", "Register") 46 |

    47 | @* Enable this once you have account confirmation enabled for password reset functionality 48 |

    49 | @Html.ActionLink("Forgot your password?", "ForgotPassword") 50 |

    *@ 51 | } 52 |
    53 |
    54 |
    55 |
    56 | @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl }) 57 |
    58 |
    59 |
    60 | 61 | @section Scripts { 62 | @Scripts.Render("~/bundles/jqueryval") 63 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.RegisterViewModel 2 | @{ 3 | ViewBag.Title = "Register"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 | @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

    Create a new account.

    12 |
    13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 |
    15 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 16 |
    17 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 18 |
    19 |
    20 |
    21 | @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) 22 |
    23 | @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 24 |
    25 |
    26 |
    27 | @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) 28 |
    29 | @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) 30 |
    31 |
    32 | 33 |
    34 | @Html.LabelFor(m => m.FirstName, new { @class = "col-md-2 control-label" }) 35 |
    36 | @Html.TextBoxFor(m => m.FirstName, new { @class = "form-control" }) 37 |
    38 |
    39 | 40 |
    41 | @Html.LabelFor(m => m.LastName, new { @class = "col-md-2 control-label" }) 42 |
    43 | @Html.TextBoxFor(m => m.LastName, new { @class = "form-control" }) 44 |
    45 |
    46 | 47 |
    48 | @Html.LabelFor(m => m.Street, new { @class = "col-md-2 control-label" }) 49 |
    50 | @Html.TextBoxFor(m => m.Street, new { @class = "form-control" }) 51 |
    52 |
    53 | 54 |
    55 | @Html.LabelFor(m => m.City, new { @class = "col-md-2 control-label" }) 56 |
    57 | @Html.TextBoxFor(m => m.City, new { @class = "form-control" }) 58 |
    59 |
    60 | 61 |
    62 | @Html.LabelFor(m => m.State, new { @class = "col-md-2 control-label" }) 63 |
    64 | @Html.TextBoxFor(m => m.State, new { @class = "form-control" }) 65 |
    66 |
    67 | 68 |
    69 | @Html.LabelFor(m => m.ZipCode, new { @class = "col-md-2 control-label" }) 70 |
    71 | @Html.TextBoxFor(m => m.ZipCode, new { @class = "form-control" }) 72 |
    73 |
    74 | 75 |
    76 |
    77 | 78 |
    79 |
    80 | } 81 | 82 | @section Scripts { 83 | @Scripts.Render("~/bundles/jqueryval") 84 | } 85 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/ResetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.ResetPasswordViewModel 2 | @{ 3 | ViewBag.Title = "Reset password"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 | @using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

    Reset your password.

    12 |
    13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 | @Html.HiddenFor(model => model.Code) 15 |
    16 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 17 |
    18 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 19 |
    20 |
    21 |
    22 | @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) 23 |
    24 | @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 25 |
    26 |
    27 |
    28 | @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) 29 |
    30 | @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) 31 |
    32 |
    33 |
    34 |
    35 | 36 |
    37 |
    38 | } 39 | 40 | @section Scripts { 41 | @Scripts.Render("~/bundles/jqueryval") 42 | } 43 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/ResetPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Reset password confirmation"; 3 | } 4 | 5 |
    6 |

    @ViewBag.Title.

    7 |
    8 |
    9 |

    10 | Your password has been reset. Please @Html.ActionLink("click here to log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" }) 11 |

    12 |
    13 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/SendCode.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.SendCodeViewModel 2 | @{ 3 | ViewBag.Title = "Send"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 | @using (Html.BeginForm("SendCode", "Account", new { ReturnUrl = Model.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { 9 | @Html.AntiForgeryToken() 10 | @Html.Hidden("rememberMe", @Model.RememberMe) 11 |

    Send verification code

    12 |
    13 |
    14 |
    15 | Select Two-Factor Authentication Provider: 16 | @Html.DropDownListFor(model => model.SelectedProvider, Model.Providers) 17 | 18 |
    19 |
    20 | } 21 | 22 | @section Scripts { 23 | @Scripts.Render("~/bundles/jqueryval") 24 | } 25 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/VerifyCode.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.VerifyCodeViewModel 2 | @{ 3 | ViewBag.Title = "Verify"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 | @using (Html.BeginForm("VerifyCode", "Account", new { ReturnUrl = Model.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { 9 | @Html.AntiForgeryToken() 10 | @Html.Hidden("provider", @Model.Provider) 11 | @Html.Hidden("rememberMe", @Model.RememberMe) 12 |

    Enter verification code

    13 |
    14 | @Html.ValidationSummary("", new { @class = "text-danger" }) 15 |
    16 | @Html.LabelFor(m => m.Code, new { @class = "col-md-2 control-label" }) 17 |
    18 | @Html.TextBoxFor(m => m.Code, new { @class = "form-control" }) 19 |
    20 |
    21 |
    22 |
    23 |
    24 | @Html.CheckBoxFor(m => m.RememberBrowser) 25 | @Html.LabelFor(m => m.RememberBrowser) 26 |
    27 |
    28 |
    29 |
    30 |
    31 | 32 |
    33 |
    34 | } 35 | 36 | @section Scripts { 37 | @Scripts.Render("~/bundles/jqueryval") 38 | } 39 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Account/_ExternalLoginsListPartial.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.ExternalLoginListViewModel 2 | @using Microsoft.Owin.Security 3 | 4 |

    Use another service to log in.

    5 |
    6 | @{ 7 | var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes(); 8 | if (loginProviders.Count() == 0) { 9 |
    10 |

    11 | There are no external authentication services configured. See this article 12 | for details on setting up this ASP.NET application to support logging in via external services. 13 |

    14 |
    15 | } 16 | else { 17 | using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = Model.ReturnUrl })) { 18 | @Html.AntiForgeryToken() 19 |
    20 |

    21 | @foreach (AuthenticationDescription p in loginProviders) { 22 | 23 | } 24 |

    25 |
    26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Admin/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Admin"; 3 | } 4 | 5 |

    Admin Pages

    6 | 7 |
    8 |

    Product Management

    9 |
    10 | @Html.ActionLink("Product Categories", "Index", "ProductCategoryManager", null, new { @class="list-group-item" }) 11 | @Html.ActionLink("Product", "Index", "ProductManager", null, new { @class = "list-group-item" }) 12 |
    13 |
    14 |
    15 |

    Order Management

    16 |
    17 | @Html.ActionLink("Orders", "Index", "OrderManager", null, new { @class = "list-group-item" }) 18 |
    19 |
    20 |
    21 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Basket/BasketSummary.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.ViewModels.BasketSummaryViewModel 2 | 3 | 7 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Basket/Checkout.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.Models.Order 2 | 3 | @using (Html.BeginForm()) 4 | { 5 | @Html.AntiForgeryToken() 6 | 7 |
    8 |

    Order

    9 |
    10 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 11 | 12 | 13 |
    14 | @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" }) 15 |
    16 | @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } }) 17 | @Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" }) 18 |
    19 |
    20 | 21 |
    22 | @Html.LabelFor(model => model.Surname, htmlAttributes: new { @class = "control-label col-md-2" }) 23 |
    24 | @Html.EditorFor(model => model.Surname, new { htmlAttributes = new { @class = "form-control" } }) 25 | @Html.ValidationMessageFor(model => model.Surname, "", new { @class = "text-danger" }) 26 |
    27 |
    28 | 29 |
    30 | @Html.LabelFor(model => model.Street, htmlAttributes: new { @class = "control-label col-md-2" }) 31 |
    32 | @Html.EditorFor(model => model.Street, new { htmlAttributes = new { @class = "form-control" } }) 33 | @Html.ValidationMessageFor(model => model.Street, "", new { @class = "text-danger" }) 34 |
    35 |
    36 | 37 |
    38 | @Html.LabelFor(model => model.City, htmlAttributes: new { @class = "control-label col-md-2" }) 39 |
    40 | @Html.EditorFor(model => model.City, new { htmlAttributes = new { @class = "form-control" } }) 41 | @Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" }) 42 |
    43 |
    44 | 45 |
    46 | @Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-2" }) 47 |
    48 | @Html.EditorFor(model => model.State, new { htmlAttributes = new { @class = "form-control" } }) 49 | @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" }) 50 |
    51 |
    52 | 53 |
    54 | @Html.LabelFor(model => model.ZipCode, htmlAttributes: new { @class = "control-label col-md-2" }) 55 |
    56 | @Html.EditorFor(model => model.ZipCode, new { htmlAttributes = new { @class = "form-control" } }) 57 | @Html.ValidationMessageFor(model => model.ZipCode, "", new { @class = "text-danger" }) 58 |
    59 |
    60 | 61 |
    62 |
    63 | 64 |
    65 |
    66 |
    67 | } 68 | 69 |
    70 | @Html.ActionLink("Back to Basket", "Index") 71 |
    72 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Basket/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Basket"; 5 | } 6 | 7 |

    Basket

    8 | 9 | 10 | 11 | 12 | 15 | 18 | 21 | 24 | 25 | 26 | 27 | @foreach (var item in Model) { 28 | 29 | 30 | 33 | 36 | 37 | 40 | 43 | 46 | 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 |
    13 | @Html.DisplayNameFor(model => model.ProductName) 14 | 16 | @Html.DisplayNameFor(model => model.Quanity) 17 | 19 | @Html.DisplayNameFor(model => model.Price) 20 | 22 | Line Total 23 |
    31 | @Html.DisplayFor(modelItem => item.ProductName) 32 | 34 | @Html.DisplayFor(modelItem => item.Quanity) 35 | 38 | @String.Format("{0:c}", item.Price) 39 | 41 | @String.Format("{0:c}", item.Price * item.Quanity) 42 | 44 | Delete 45 |
    Basket Total@String.Format("{0:c}", (from p in Model select p.Price * p.Quanity).Sum())Checkout
    55 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Basket/ThankYou.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Thank You"; 3 | } 4 | 5 |

    Thank You

    6 | Thank you for your order.

    7 | Your Order Id = @ViewBag.OrderId 8 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

    @ViewBag.Title.

    5 |

    @ViewBag.Message

    6 | 7 |

    Use this area to provide additional information.

    8 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

    @ViewBag.Title.

    5 |

    @ViewBag.Message

    6 | 7 |
    8 | One Microsoft Way
    9 | Redmond, WA 98052-6399
    10 | P: 11 | 425.555.0100 12 |
    13 | 14 |
    15 | Support: Support@example.com
    16 | Marketing: Marketing@example.com 17 |
    -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Home/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.Models.Product 2 | 3 | @{ 4 | ViewBag.Title = Model.Name + " Details"; 5 | } 6 | 7 |

    @Html.DisplayFor(model=>model.Name)

    8 | 9 |
    10 |
    11 | 12 |
    13 |
    14 |
    15 | 16 | 17 |
    18 | @Html.DisplayNameFor(model => model.Description) 19 |
    20 | 21 |
    22 | @Html.DisplayFor(model => model.Description) 23 |
    24 | 25 |
    26 | @Html.DisplayNameFor(model => model.Price) 27 |
    28 | 29 |
    30 | $@Html.DisplayFor(model => model.Price) 31 |
    32 | 33 |
    34 |
    Add To Basket
    35 | 36 |
    37 |
    @Html.ActionLink("Back to List", "Index")
    38 |
    39 |
    40 |
    41 |
    42 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.ViewModels.ProductListViewModel 2 | @{ 3 | ViewBag.Title = "Home Page"; 4 | } 5 | 6 |

    Products

    7 | 8 |
    9 |

    Filter by Category

    10 |
    11 | @Html.ActionLink("All", "Index", null, new { @class = Request["Category"]==null? "list-group-item active" : "list-group-item" }) 12 | @foreach (var cat in Model.ProductCategories) { 13 | @Html.ActionLink(cat.Category, "Index", new { Category=cat.Category }, new { @class = Request["Category"] == cat.Category ? "list-group-item active" : "list-group-item" }) 14 | } 15 |
    16 |
    17 |
    18 | 19 | @foreach (var item in Model.Products) 20 | { 21 | 22 |
    23 |
    24 | 25 |
    26 |
    27 | @Html.ActionLink(item.Name, "Details", new { id = item.Id }) 28 |
    29 |
    30 |

    @item.Description

    31 |
    32 |
    33 |

    @item.Price

    34 |
    35 |
    36 | Add to Basket 37 |
    38 |
    39 | } 40 |
    41 |
    42 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Manage/AddPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.AddPhoneNumberViewModel 2 | @{ 3 | ViewBag.Title = "Phone Number"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 | @using (Html.BeginForm("AddPhoneNumber", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

    Add a phone number

    12 |
    13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 |
    15 | @Html.LabelFor(m => m.Number, new { @class = "col-md-2 control-label" }) 16 |
    17 | @Html.TextBoxFor(m => m.Number, new { @class = "form-control" }) 18 |
    19 |
    20 |
    21 |
    22 | 23 |
    24 |
    25 | } 26 | 27 | @section Scripts { 28 | @Scripts.Render("~/bundles/jqueryval") 29 | } 30 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Manage/ChangePassword.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.ChangePasswordViewModel 2 | @{ 3 | ViewBag.Title = "Change Password"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 | @using (Html.BeginForm("ChangePassword", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

    Change Password Form

    12 |
    13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 |
    15 | @Html.LabelFor(m => m.OldPassword, new { @class = "col-md-2 control-label" }) 16 |
    17 | @Html.PasswordFor(m => m.OldPassword, new { @class = "form-control" }) 18 |
    19 |
    20 |
    21 | @Html.LabelFor(m => m.NewPassword, new { @class = "col-md-2 control-label" }) 22 |
    23 | @Html.PasswordFor(m => m.NewPassword, new { @class = "form-control" }) 24 |
    25 |
    26 |
    27 | @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) 28 |
    29 | @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) 30 |
    31 |
    32 |
    33 |
    34 | 35 |
    36 |
    37 | } 38 | @section Scripts { 39 | @Scripts.Render("~/bundles/jqueryval") 40 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Manage/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.IndexViewModel 2 | @{ 3 | ViewBag.Title = "Manage"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 |

    @ViewBag.StatusMessage

    9 |
    10 |

    Change your account settings

    11 |
    12 |
    13 |
    Password:
    14 |
    15 | [ 16 | @if (Model.HasPassword) 17 | { 18 | @Html.ActionLink("Change your password", "ChangePassword") 19 | } 20 | else 21 | { 22 | @Html.ActionLink("Create", "SetPassword") 23 | } 24 | ] 25 |
    26 |
    External Logins:
    27 |
    28 | @Model.Logins.Count [ 29 | @Html.ActionLink("Manage", "ManageLogins") ] 30 |
    31 | @* 32 | Phone Numbers can used as a second factor of verification in a two-factor authentication system. 33 | 34 | See this article 35 | for details on setting up this ASP.NET application to support two-factor authentication using SMS. 36 | 37 | Uncomment the following block after you have set up two-factor authentication 38 | *@ 39 | @* 40 |
    Phone Number:
    41 |
    42 | @(Model.PhoneNumber ?? "None") 43 | @if (Model.PhoneNumber != null) 44 | { 45 |
    46 | [  @Html.ActionLink("Change", "AddPhoneNumber")  ] 47 | using (Html.BeginForm("RemovePhoneNumber", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 48 | { 49 | @Html.AntiForgeryToken() 50 | [] 51 | } 52 | } 53 | else 54 | { 55 | [  @Html.ActionLink("Add", "AddPhoneNumber") 56 | } 57 |
    58 | *@ 59 |
    Two-Factor Authentication:
    60 |
    61 |

    62 | There are no two-factor authentication providers configured. See this article 63 | for details on setting up this ASP.NET application to support two-factor authentication. 64 |

    65 | @*@if (Model.TwoFactor) 66 | { 67 | using (Html.BeginForm("DisableTwoFactorAuthentication", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 68 | { 69 | @Html.AntiForgeryToken() 70 | Enabled 71 | 72 | 73 | } 74 | } 75 | else 76 | { 77 | using (Html.BeginForm("EnableTwoFactorAuthentication", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 78 | { 79 | @Html.AntiForgeryToken() 80 | Disabled 81 | 82 | 83 | } 84 | }*@ 85 |
    86 |
    87 |
    88 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Manage/ManageLogins.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.ManageLoginsViewModel 2 | @using Microsoft.Owin.Security 3 | @{ 4 | ViewBag.Title = "Manage your external logins"; 5 | } 6 | 7 |

    @ViewBag.Title.

    8 | 9 |

    @ViewBag.StatusMessage

    10 | @{ 11 | var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes(); 12 | if (loginProviders.Count() == 0) { 13 |
    14 |

    15 | There are no external authentication services configured. See this article 16 | for details on setting up this ASP.NET application to support logging in via external services. 17 |

    18 |
    19 | } 20 | else 21 | { 22 | if (Model.CurrentLogins.Count > 0) 23 | { 24 |

    Registered Logins

    25 | 26 | 27 | @foreach (var account in Model.CurrentLogins) 28 | { 29 | 30 | 31 | 49 | 50 | } 51 | 52 |
    @account.LoginProvider 32 | @if (ViewBag.ShowRemoveButton) 33 | { 34 | using (Html.BeginForm("RemoveLogin", "Manage")) 35 | { 36 | @Html.AntiForgeryToken() 37 |
    38 | @Html.Hidden("loginProvider", account.LoginProvider) 39 | @Html.Hidden("providerKey", account.ProviderKey) 40 | 41 |
    42 | } 43 | } 44 | else 45 | { 46 | @:   47 | } 48 |
    53 | } 54 | if (Model.OtherLogins.Count > 0) 55 | { 56 | using (Html.BeginForm("LinkLogin", "Manage")) 57 | { 58 | @Html.AntiForgeryToken() 59 |
    60 |

    61 | @foreach (AuthenticationDescription p in Model.OtherLogins) 62 | { 63 | 64 | } 65 |

    66 |
    67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Manage/SetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.SetPasswordViewModel 2 | @{ 3 | ViewBag.Title = "Create Password"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 |

    8 | You do not have a local username/password for this site. Add a local 9 | account so you can log in without an external login. 10 |

    11 | 12 | @using (Html.BeginForm("SetPassword", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 13 | { 14 | @Html.AntiForgeryToken() 15 | 16 |

    Create Local Login

    17 |
    18 | @Html.ValidationSummary("", new { @class = "text-danger" }) 19 |
    20 | @Html.LabelFor(m => m.NewPassword, new { @class = "col-md-2 control-label" }) 21 |
    22 | @Html.PasswordFor(m => m.NewPassword, new { @class = "form-control" }) 23 |
    24 |
    25 |
    26 | @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) 27 |
    28 | @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) 29 |
    30 |
    31 |
    32 |
    33 | 34 |
    35 |
    36 | } 37 | @section Scripts { 38 | @Scripts.Render("~/bundles/jqueryval") 39 | } -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Manage/VerifyPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.WebUI.Models.VerifyPhoneNumberViewModel 2 | @{ 3 | ViewBag.Title = "Verify Phone Number"; 4 | } 5 | 6 |

    @ViewBag.Title.

    7 | 8 | @using (Html.BeginForm("VerifyPhoneNumber", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 | @Html.Hidden("phoneNumber", @Model.PhoneNumber) 12 |

    Enter verification code

    13 |
    @ViewBag.Status
    14 |
    15 | @Html.ValidationSummary("", new { @class = "text-danger" }) 16 |
    17 | @Html.LabelFor(m => m.Code, new { @class = "col-md-2 control-label" }) 18 |
    19 | @Html.TextBoxFor(m => m.Code, new { @class = "form-control" }) 20 |
    21 |
    22 |
    23 |
    24 | 25 |
    26 |
    27 | } 28 | 29 | @section Scripts { 30 | @Scripts.Render("~/bundles/jqueryval") 31 | } 32 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/OrderManager/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | 4 | 5 | 8 | 11 | 14 | 17 | 18 | 21 | 22 | 23 | 24 | @foreach (var item in Model) { 25 | 26 | 29 | 32 | 35 | 38 | 39 | 42 | 45 | 46 | } 47 | 48 |
    6 | @Html.DisplayNameFor(model => model.CreatedAt) 7 | 9 | @Html.DisplayNameFor(model => model.FirstName) 10 | 12 | @Html.DisplayNameFor(model => model.Surname) 13 | 15 | @Html.DisplayNameFor(model => model.Email) 16 | 19 | @Html.DisplayNameFor(model => model.OrderStatus) 20 |
    27 | @Html.DisplayFor(modelItem => item.CreatedAt) 28 | 30 | @Html.DisplayFor(modelItem => item.FirstName) 31 | 33 | @Html.DisplayFor(modelItem => item.Surname) 34 | 36 | @Html.DisplayFor(modelItem => item.Email) 37 | 40 | @Html.DisplayFor(modelItem => item.OrderStatus) 41 | 43 | @Html.ActionLink("Manage Order", "UpdateOrder", new { id=item.Id }) 44 |
    49 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/OrderManager/OrderItems.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | 4 | 5 | 6 | 9 | 12 | 15 | 16 | 17 | 18 | @foreach (var item in Model) { 19 | 20 | 21 | 24 | 27 | 30 | 33 | 34 | } 35 | 36 | 37 | 40 | 43 | 44 | 45 |
    7 | @Html.DisplayNameFor(model => model.ProductName) 8 | 10 | @Html.DisplayNameFor(model => model.Price) 11 | 13 | @Html.DisplayNameFor(model => model.Quanity) 14 | Line Order
    22 | @Html.DisplayFor(modelItem => item.ProductName) 23 | 25 | @Html.DisplayFor(modelItem => item.Price) 26 | 28 | @Html.DisplayFor(modelItem => item.Quanity) 29 | 31 | @String.Format("{0:c}", item.Price * item.Quanity) 32 |
    38 | Order Total 39 | 41 | @String.Format("{0:c}", (from p in Model select p.Quanity * p.Price).Sum()) 42 |
    46 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/OrderManager/UpdateOrder.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.Models.Order 2 | 3 | @using (Html.BeginForm()) 4 | { 5 | @Html.AntiForgeryToken() 6 | 7 |
    8 |

    Order

    9 |
    10 | @Html.HiddenFor(model => model.Id) 11 | 12 |
    13 |
    14 | @Html.LabelFor(model => model.OrderStatus, htmlAttributes: new { @class = "control-label col-md-2" }) 15 |
    16 | @Html.DropDownListFor(model => model.OrderStatus, new SelectList(ViewBag.StatusList), new { @class = "form-control" }) 17 |
    18 |
    19 | 20 |
    21 | @Html.LabelFor(model => model.CreatedAt, htmlAttributes: new { @class = "control-label col-md-2" }) 22 |
    23 | @Html.DisplayFor(model => model.CreatedAt, new { htmlAttributes = new { @class = "form-control" } }) 24 |
    25 |
    26 | 27 |
    28 | @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" }) 29 |
    30 | @Html.DisplayFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } }) 31 |
    32 |
    33 | 34 |
    35 | @Html.LabelFor(model => model.Surname, htmlAttributes: new { @class = "control-label col-md-2" }) 36 |
    37 | @Html.DisplayFor(model => model.Surname, new { htmlAttributes = new { @class = "form-control" } }) 38 |
    39 |
    40 | 41 |
    42 | @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" }) 43 |
    44 | @Html.DisplayFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } }) 45 |
    46 |
    47 | 48 |
    49 |
    50 |
    51 | @Html.LabelFor(model => model.Street, htmlAttributes: new { @class = "control-label col-md-2" }) 52 |
    53 | @Html.DisplayFor(model => model.Street, new { htmlAttributes = new { @class = "form-control" } }) 54 |
    55 |
    56 | 57 |
    58 | @Html.LabelFor(model => model.City, htmlAttributes: new { @class = "control-label col-md-2" }) 59 |
    60 | @Html.DisplayFor(model => model.City, new { htmlAttributes = new { @class = "form-control" } }) 61 |
    62 |
    63 | 64 |
    65 | @Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-2" }) 66 |
    67 | @Html.DisplayFor(model => model.State, new { htmlAttributes = new { @class = "form-control" } }) 68 |
    69 |
    70 | 71 |
    72 | @Html.LabelFor(model => model.ZipCode, htmlAttributes: new { @class = "control-label col-md-2" }) 73 |
    74 | @Html.DisplayFor(model => model.ZipCode, new { htmlAttributes = new { @class = "form-control" } }) 75 |
    76 |
    77 |
    78 | 79 |
    80 |
    81 | 82 |
    83 |
    84 |
    85 | 86 | @Html.Partial("OrderItems", Model.OrderItems) 87 | } 88 | 89 |
    90 | @Html.ActionLink("Back to List", "Index") 91 |
    92 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/ProductCategoryManager/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.Models.ProductCategory 2 | 3 | @{ 4 | ViewBag.Title = "Create"; 5 | } 6 | 7 |

    Create

    8 | 9 | 10 | @using (Html.BeginForm()) 11 | { 12 | @Html.AntiForgeryToken() 13 | 14 |
    15 |

    ProductCategory

    16 |
    17 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 18 |
    19 | @Html.LabelFor(model => model.Category, htmlAttributes: new { @class = "control-label col-md-2" }) 20 |
    21 | @Html.EditorFor(model => model.Category, new { htmlAttributes = new { @class = "form-control" } }) 22 | @Html.ValidationMessageFor(model => model.Category, "", new { @class = "text-danger" }) 23 |
    24 |
    25 | 26 |
    27 |
    28 | 29 |
    30 |
    31 |
    32 | } 33 | 34 |
    35 | @Html.ActionLink("Back to List", "Index") 36 |
    37 | 38 | @section Scripts { 39 | @Scripts.Render("~/bundles/jqueryval") 40 | } 41 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/ProductCategoryManager/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.Models.ProductCategory 2 | 3 | @{ 4 | ViewBag.Title = "Delete"; 5 | } 6 | 7 |

    Delete

    8 | 9 |

    Are you sure you want to delete this?

    10 |
    11 |

    ProductCategory

    12 |
    13 |
    14 |
    15 | @Html.DisplayNameFor(model => model.Category) 16 |
    17 | 18 |
    19 | @Html.DisplayFor(model => model.Category) 20 |
    21 | 22 |
    23 | 24 | @using (Html.BeginForm()) { 25 | @Html.AntiForgeryToken() 26 | 27 |
    28 | | 29 | @Html.ActionLink("Back to List", "Index") 30 |
    31 | } 32 |
    33 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/ProductCategoryManager/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.Models.ProductCategory 2 | 3 | @{ 4 | ViewBag.Title = "Edit"; 5 | } 6 | 7 |

    Edit

    8 | 9 | 10 | @using (Html.BeginForm()) 11 | { 12 | @Html.AntiForgeryToken() 13 | 14 |
    15 |

    ProductCategory

    16 |
    17 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 18 | @Html.HiddenFor(model => model.Id) 19 | 20 |
    21 | @Html.LabelFor(model => model.Category, htmlAttributes: new { @class = "control-label col-md-2" }) 22 |
    23 | @Html.EditorFor(model => model.Category, new { htmlAttributes = new { @class = "form-control" } }) 24 | @Html.ValidationMessageFor(model => model.Category, "", new { @class = "text-danger" }) 25 |
    26 |
    27 | 28 |
    29 |
    30 | 31 |
    32 |
    33 |
    34 | } 35 | 36 |
    37 | @Html.ActionLink("Back to List", "Index") 38 |
    39 | 40 | @section Scripts { 41 | @Scripts.Render("~/bundles/jqueryval") 42 | } 43 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/ProductCategoryManager/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Index"; 5 | } 6 | 7 |

    Index

    8 | 9 |

    10 | @Html.ActionLink("Create New", "Create") 11 |

    12 | 13 | 14 | 17 | 18 | 19 | 20 | @foreach (var item in Model) { 21 | 22 | 25 | 29 | 30 | } 31 | 32 |
    15 | @Html.DisplayNameFor(model => model.Category) 16 |
    23 | @Html.DisplayFor(modelItem => item.Category) 24 | 26 | @Html.ActionLink("Edit", "Edit", new { id=item.Id }) | 27 | @Html.ActionLink("Delete", "Delete", new { id=item.Id }) 28 |
    33 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/ProductManager/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.ViewModels.ProductManagerViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Create"; 5 | } 6 | 7 |

    Create

    8 | 9 | 10 | @using (Html.BeginForm("Create", "ProductManager", FormMethod.Post, new { encType = "multipart/form-data" })) 11 | { 12 | @Html.AntiForgeryToken() 13 | 14 |
    15 |

    Product

    16 |
    17 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 18 |
    19 | @Html.LabelFor(model => model.Product.Name, htmlAttributes: new { @class = "control-label col-md-2" }) 20 |
    21 | @Html.EditorFor(model => model.Product.Name, new { htmlAttributes = new { @class = "form-control" } }) 22 | @Html.ValidationMessageFor(model => model.Product.Name, "", new { @class = "text-danger" }) 23 |
    24 |
    25 | 26 |
    27 | @Html.LabelFor(model => model.Product.Description, htmlAttributes: new { @class = "control-label col-md-2" }) 28 |
    29 | @Html.EditorFor(model => model.Product.Description, new { htmlAttributes = new { @class = "form-control" } }) 30 | @Html.ValidationMessageFor(model => model.Product.Description, "", new { @class = "text-danger" }) 31 |
    32 |
    33 | 34 |
    35 | @Html.LabelFor(model => model.Product.Price, htmlAttributes: new { @class = "control-label col-md-2" }) 36 |
    37 | @Html.EditorFor(model => model.Product.Price, new { htmlAttributes = new { @class = "form-control" } }) 38 | @Html.ValidationMessageFor(model => model.Product.Price, "", new { @class = "text-danger" }) 39 |
    40 |
    41 | 42 |
    43 | @Html.LabelFor(model => model.Product.Category, htmlAttributes: new { @class = "control-label col-md-2" }) 44 |
    45 | @Html.DropDownListFor(model =>model.Product.Category, new SelectList(Model.ProductCategories, "Category", "Category"), new { htmlAttributes = new { @class = "form-control" } }) 46 |
    47 |
    48 | 49 |
    50 | @Html.LabelFor(model => model.Product.Image, htmlAttributes: new { @class = "control-label col-md-2" }) 51 |
    52 | 53 |
    54 |
    55 | 56 |
    57 |
    58 | 59 |
    60 |
    61 |
    62 | } 63 | 64 |
    65 | @Html.ActionLink("Back to List", "Index") 66 |
    67 | 68 | @section Scripts { 69 | @Scripts.Render("~/bundles/jqueryval") 70 | } 71 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/ProductManager/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.Models.Product 2 | 3 | @{ 4 | ViewBag.Title = "Delete"; 5 | } 6 | 7 |

    Delete

    8 | 9 |

    Are you sure you want to delete this?

    10 |
    11 |

    Product

    12 |
    13 |
    14 |
    15 | @Html.DisplayNameFor(model => model.Name) 16 |
    17 | 18 |
    19 | @Html.DisplayFor(model => model.Name) 20 |
    21 | 22 |
    23 | @Html.DisplayNameFor(model => model.Description) 24 |
    25 | 26 |
    27 | @Html.DisplayFor(model => model.Description) 28 |
    29 | 30 |
    31 | @Html.DisplayNameFor(model => model.Price) 32 |
    33 | 34 |
    35 | @Html.DisplayFor(model => model.Price) 36 |
    37 | 38 |
    39 | @Html.DisplayNameFor(model => model.Category) 40 |
    41 | 42 |
    43 | @Html.DisplayFor(model => model.Category) 44 |
    45 | 46 |
    47 | @Html.DisplayNameFor(model => model.Image) 48 |
    49 | 50 |
    51 | @Html.DisplayFor(model => model.Image) 52 |
    53 | 54 |
    55 | 56 | @using (Html.BeginForm()) { 57 | @Html.AntiForgeryToken() 58 | 59 |
    60 | | 61 | @Html.ActionLink("Back to List", "Index") 62 |
    63 | } 64 |
    65 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/ProductManager/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model MyShop.Core.ViewModels.ProductManagerViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Edit"; 5 | } 6 | 7 |

    Edit

    8 | 9 | 10 | @using (Html.BeginForm("Edit", "ProductManager", FormMethod.Post, new { encType="multipart/form-data" })) 11 | { 12 | @Html.AntiForgeryToken() 13 | 14 |
    15 |

    Product

    16 |
    17 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 18 | @Html.HiddenFor(model => model.Product.Id) 19 | 20 |
    21 | 22 |
    23 |
    24 | 25 |
    26 | @Html.LabelFor(model => model.Product.Name, htmlAttributes: new { @class = "control-label col-md-2" }) 27 |
    28 | @Html.EditorFor(model => model.Product.Name, new { htmlAttributes = new { @class = "form-control" } }) 29 | @Html.ValidationMessageFor(model => model.Product.Name, "", new { @class = "text-danger" }) 30 |
    31 |
    32 | 33 |
    34 | @Html.LabelFor(model => model.Product.Description, htmlAttributes: new { @class = "control-label col-md-2" }) 35 |
    36 | @Html.EditorFor(model => model.Product.Description, new { htmlAttributes = new { @class = "form-control" } }) 37 | @Html.ValidationMessageFor(model => model.Product.Description, "", new { @class = "text-danger" }) 38 |
    39 |
    40 | 41 |
    42 | @Html.LabelFor(model => model.Product.Price, htmlAttributes: new { @class = "control-label col-md-2" }) 43 |
    44 | @Html.EditorFor(model => model.Product.Price, new { htmlAttributes = new { @class = "form-control" } }) 45 | @Html.ValidationMessageFor(model => model.Product.Price, "", new { @class = "text-danger" }) 46 |
    47 |
    48 | 49 |
    50 | @Html.LabelFor(model => model.Product.Category, htmlAttributes: new { @class = "control-label col-md-2" }) 51 |
    52 | @Html.DropDownListFor(model => model.Product.Category, new SelectList(Model.ProductCategories, "Category", "Category"), new { htmlAttributes = new { @class = "form-control" } }) 53 |
    54 |
    55 | 56 |
    57 | @Html.LabelFor(model => model.Product.Image, htmlAttributes: new { @class = "control-label col-md-2" }) 58 |
    59 | 60 |
    61 |
    62 | 63 |
    64 |
    65 | 66 |
    67 |
    68 |
    69 |
    70 | } 71 | 72 |
    73 | @Html.ActionLink("Back to List", "Index") 74 |
    75 | 76 | @section Scripts { 77 | @Scripts.Render("~/bundles/jqueryval") 78 | } 79 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/ProductManager/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Index"; 5 | } 6 | 7 |

    Index

    8 | 9 |

    10 | @Html.ActionLink("Create New", "Create") 11 |

    12 | 13 | 14 | 15 | 18 | 21 | 24 | 27 | 28 | 29 | 30 | @foreach (var item in Model) { 31 | 32 | 35 | 38 | 41 | 44 | 47 | 51 | 52 | } 53 | 54 |
    16 | @Html.DisplayNameFor(model => model.Name) 17 | 19 | @Html.DisplayNameFor(model => model.Description) 20 | 22 | @Html.DisplayNameFor(model => model.Price) 23 | 25 | @Html.DisplayNameFor(model => model.Category) 26 |
    33 | 34 | 36 | @Html.DisplayFor(modelItem => item.Name) 37 | 39 | @Html.DisplayFor(modelItem => item.Description) 40 | 42 | @Html.DisplayFor(modelItem => item.Price) 43 | 45 | @Html.DisplayFor(modelItem => item.Category) 46 | 48 | @Html.ActionLink("Edit", "Edit", new { id=item.Id }) | 49 | @Html.ActionLink("Delete", "Delete", new { id=item.Id }) 50 |
    55 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model System.Web.Mvc.HandleErrorInfo 2 | 3 | @{ 4 | ViewBag.Title = "Error"; 5 | } 6 | 7 |

    Error.

    8 |

    An error occurred while processing your request.

    9 | 10 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Shared/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @model System.Web.Mvc.HandleErrorInfo 2 | 3 | @{ 4 | ViewBag.Title = "Locked Out"; 5 | } 6 | 7 |
    8 |

    Locked out.

    9 |

    This account has been locked out, please try again later.

    10 |
    11 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 12 | 37 |
    38 | @RenderBody() 39 |
    40 |
    41 |

    © @DateTime.Now.Year - My ASP.NET Application

    42 |
    43 |
    44 | 45 | @Scripts.Render("~/bundles/jquery") 46 | @Scripts.Render("~/bundles/bootstrap") 47 | @RenderSection("scripts", required: false) 48 | 49 | 50 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNet.Identity 2 | @if (Request.IsAuthenticated) 3 | { 4 | using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) 5 | { 6 | @Html.AntiForgeryToken() 7 | 8 | 14 | } 15 | } 16 | else 17 | { 18 | 22 | } 23 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
    7 |
    8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/completecoder/MyShop/25e6098b113dffcc545f4fc493e01f7d34dd31f7/MyShop/MyShop.WebUI/favicon.ico -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/completecoder/MyShop/25e6098b113dffcc545f4fc493e01f7d34dd31f7/MyShop/MyShop.WebUI/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/completecoder/MyShop/25e6098b113dffcc545f4fc493e01f7d34dd31f7/MyShop/MyShop.WebUI/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/completecoder/MyShop/25e6098b113dffcc545f4fc493e01f7d34dd31f7/MyShop/MyShop.WebUI/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/completecoder/MyShop/25e6098b113dffcc545f4fc493e01f7d34dd31f7/MyShop/MyShop.WebUI/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /MyShop/MyShop.WebUI/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /MyShop/MyShop.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2002 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyShop.Core", "MyShop.Core\MyShop.Core.csproj", "{9B029460-6F4E-46AE-9B88-08C5FE08C0A4}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyShop.Services", "MyShop.Services\MyShop.Services.csproj", "{462AA931-D9E7-4B8A-840B-C8026F2C0FC0}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyShop.DataAccess.SQL", "MyShop.DataAccess.SQL\MyShop.DataAccess.SQL.csproj", "{3A4704F8-042D-4450-A79A-AA096ED4F5CD}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyShop.DataAccess.InMemory", "MyShop.DataAccess.InMemory\MyShop.DataAccess.InMemory.csproj", "{E7FD92A1-7304-4F70-9BA5-E214CB28A863}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyShop.WebUI", "MyShop.WebUI\MyShop.WebUI.csproj", "{4325FEA9-EBA9-49CA-B09D-113B11C33F48}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyShop.WebUI.Tests", "MyShop.WebUI.Tests\MyShop.WebUI.Tests.csproj", "{78F25574-63EC-434B-9B13-DD3651D2F489}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Release|Any CPU = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {9B029460-6F4E-46AE-9B88-08C5FE08C0A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {9B029460-6F4E-46AE-9B88-08C5FE08C0A4}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {9B029460-6F4E-46AE-9B88-08C5FE08C0A4}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {9B029460-6F4E-46AE-9B88-08C5FE08C0A4}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {462AA931-D9E7-4B8A-840B-C8026F2C0FC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {462AA931-D9E7-4B8A-840B-C8026F2C0FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {462AA931-D9E7-4B8A-840B-C8026F2C0FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {462AA931-D9E7-4B8A-840B-C8026F2C0FC0}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {3A4704F8-042D-4450-A79A-AA096ED4F5CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {3A4704F8-042D-4450-A79A-AA096ED4F5CD}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {3A4704F8-042D-4450-A79A-AA096ED4F5CD}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {3A4704F8-042D-4450-A79A-AA096ED4F5CD}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {E7FD92A1-7304-4F70-9BA5-E214CB28A863}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {E7FD92A1-7304-4F70-9BA5-E214CB28A863}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {E7FD92A1-7304-4F70-9BA5-E214CB28A863}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {E7FD92A1-7304-4F70-9BA5-E214CB28A863}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {4325FEA9-EBA9-49CA-B09D-113B11C33F48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {4325FEA9-EBA9-49CA-B09D-113B11C33F48}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {4325FEA9-EBA9-49CA-B09D-113B11C33F48}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {4325FEA9-EBA9-49CA-B09D-113B11C33F48}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {78F25574-63EC-434B-9B13-DD3651D2F489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {78F25574-63EC-434B-9B13-DD3651D2F489}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {78F25574-63EC-434B-9B13-DD3651D2F489}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {78F25574-63EC-434B-9B13-DD3651D2F489}.Release|Any CPU.Build.0 = Release|Any CPU 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | GlobalSection(ExtensibilityGlobals) = postSolution 53 | SolutionGuid = {16C8D974-5A6E-4E52-A806-B9ACB3996C7C} 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # My Source Code 2 | This repository contains my completed and working source code for the project in my ASP.NET MVC Training course. 3 | 4 | Please follow my Blog at https://completecloud.guru for useful articles 5 | and my facebook page at https://www.facebook.com/completecloud.guru/ 6 | 7 | Finally, I have a new YouTube channel coming soon, so please follow one of the above to be updated when it's released! 8 | --------------------------------------------------------------------------------