├── .gitignore ├── LICENSE.txt ├── Orders.com.BLL.Tests ├── Commands │ ├── CreateProductCommandTests.cs │ ├── DeleteOrderCommandTests.cs │ ├── DeleteProductCommandTests.cs │ └── ShipOrderItemCommandTests.cs ├── Orders.com.BLL.Tests.csproj ├── Properties │ └── AssemblyInfo.cs ├── Rules │ ├── CanDeleteCategoryRuleTests.cs │ ├── CanDeleteCustomerRuleTests.cs │ ├── CanDeleteProductRuleTests.cs │ ├── CanShipOrderItemRuleTests.cs │ ├── CanSubmitOrderItemRuleTests.cs │ ├── CannotEditPropertyRuleTests.cs │ ├── OrderItemAmountValidityRuleTests.cs │ ├── OrderItemPriceValidityRuleTests.cs │ ├── ValidOrderItemStatusForDeleteRuleTests.cs │ ├── ValidOrderItemStatusForUpdateRuleTests.cs │ └── ValidOrderStatusForUpdateRuleTests.cs ├── TransactionContextStub.cs ├── app.config └── packages.config ├── Orders.com.BLL ├── Commands │ ├── CreateProductCommand.cs │ ├── DeleteOrderCommand.cs │ ├── DeleteProductCommand.cs │ └── ShipOrderItemCommand.cs ├── DataProxy │ ├── ICategoryDataProxy.cs │ ├── ICustomerDataProxy.cs │ ├── IOrderDataProxy.cs │ ├── IOrderItemDataProxy.cs │ ├── IOrderStatusDataProxy.cs │ ├── IOrdersDotComDataProxy.cs │ ├── IProductDataProxy.cs │ └── InventoryItemDataProxy.cs ├── Domain │ ├── Category.cs │ ├── Customer.cs │ ├── DomainBase.cs │ ├── IOrderStatusIDContainer.cs │ ├── InventoryItem.cs │ ├── Order.cs │ ├── OrderItem.cs │ ├── OrderStatus.cs │ └── Product.cs ├── Extensions │ ├── DateExtensions.cs │ ├── IVersionContainerExtensions.cs │ ├── OrderItemExtensions.cs │ └── OrderStates.cs ├── Orders.com.BLL.csproj ├── Properties │ └── AssemblyInfo.cs ├── QueryData │ └── OrderInfo.cs ├── Rules │ ├── CanDeleteCategoryRule.cs │ ├── CanDeleteCustomerRule.cs │ ├── CanDeleteProductRule.cs │ ├── CanShipOrderItemRule.cs │ ├── CanSubmitOrderItemRule.cs │ ├── CannotEditPropertyRule.cs │ ├── OrderItemAmountValidityRule.cs │ ├── OrderItemPriceValidityRule.cs │ ├── ValidOrderItemStatusForDeleteRule.cs │ ├── ValidOrderItemStatusForUpdateRule.cs │ └── ValidOrderStatusForUpdateRule.cs ├── Services │ ├── CategoryService.cs │ ├── CustomerService.cs │ ├── ICategoryService.cs │ ├── ICustomerService.cs │ ├── IInventoryItemService.cs │ ├── IOrderItemService.cs │ ├── IOrderService.cs │ ├── IOrderStatusService.cs │ ├── IProductService.cs │ ├── IntentoryItemService.cs │ ├── OrderItemClientService.cs │ ├── OrderItemService.cs │ ├── OrderService.cs │ ├── OrderStatusService.cs │ ├── OrdersDotComServiceBase.cs │ ├── ProductClientService.cs │ └── ProductService.cs ├── project.json └── project.lock.json ├── Orders.com.DAL.EF ├── App.config ├── CategoryRepository.cs ├── CustomerRepository.cs ├── InventoryItemRepository.cs ├── MapsterHelper.cs ├── Migrations │ ├── 201511301846134_Initial.Designer.cs │ ├── 201511301846134_Initial.cs │ ├── 201511301846134_Initial.resx │ └── Configuration.cs ├── OrderItemRepository.cs ├── OrderRepository.cs ├── OrderStatusRepository.cs ├── Orders.com.DAL.EF.csproj ├── OrdersDotComContext.cs ├── OrdersDotComRepositoryBase.cs ├── ProductRepository.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── Orders.com.DAL.Http ├── CategoriesHttpServiceProxy.cs ├── CustomersHttpServiceProxy.cs ├── HttpClientExtensions.cs ├── InventoryItemsHttpServiceProxy.cs ├── OrderItemsHttpServiceProxy.cs ├── Orders.com.DAL.Http.csproj ├── OrdersDotComHttpProxyBase.cs ├── OrdersHttpServiceProxy.cs ├── ProductsHttpServiceProxy.cs ├── Properties │ └── AssemblyInfo.cs ├── project.json └── project.lock.json ├── Orders.com.DAL.InMemory ├── CategoryRepository.cs ├── CustomerRepository.cs ├── InventoryItemRepository.cs ├── OrderItemRepository.cs ├── OrderRepository.cs ├── OrderStatusRepository.cs ├── Orders.com.DAL.InMemory.csproj ├── OrdersDotComRepositoryBase.cs ├── ProductRepository.cs ├── Properties │ └── AssemblyInfo.cs ├── project.json └── project.lock.json ├── Orders.com.WPF ├── App.config ├── App.xaml ├── App.xaml.cs ├── Command.cs ├── Converters │ ├── DecimalConverter.cs │ ├── ErrorsConverter.cs │ └── VisibilityConverter.cs ├── CustomerOrderWindow.xaml ├── CustomerOrderWindow.xaml.cs ├── DTCTransactionContext.cs ├── EventAggregator.cs ├── Images │ ├── add.png │ ├── cancel.png │ ├── delete.png │ ├── edit.png │ ├── next.png │ ├── save.png │ ├── sync.png │ └── warning.png ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── OrderInsertedEvent.cs ├── OrderUpdatedEvent.cs ├── Orders.com.WPF.csproj ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── VM │ ├── CategoriesVM.cs │ ├── CategoryVM.cs │ ├── CustomerOrderVM.cs │ ├── CustomerVM.cs │ ├── CustomersVM.cs │ ├── EntityViewModelBase.cs │ ├── InventoryItemVM.cs │ ├── InventoryItemsVM.cs │ ├── MainWindowVM.cs │ ├── OrderItemVM.cs │ ├── OrderVM.cs │ ├── OrdersDotComVMBase.cs │ ├── OrdersVM.cs │ ├── ProductVM.cs │ ├── ProductsVM.cs │ └── ViewModelBase.cs └── packages.config ├── Orders.com.Web.Api ├── App_Start │ ├── FilterConfig.cs │ ├── NinjectWebCommon.cs │ ├── RouteConfig.cs │ └── WebApiConfig.cs ├── Configuration │ ├── DIConfig.cs │ ├── DIConfigList.cs │ ├── DIConfigSection.cs │ ├── DIDefaultPropConfig.cs │ └── DIDefaultPropConfigList.cs ├── Constants.cs ├── Controllers │ ├── ApiControllerBase.cs │ ├── CategoriesController.cs │ ├── CustomersController.cs │ ├── InventoryItemsController.cs │ ├── OrderItemsController.cs │ ├── OrdersController.cs │ └── ProductsController.cs ├── DTCTransactionContext.cs ├── DependencyInjection.config ├── Extensions │ ├── IDomainObjectExtensions.cs │ └── ModelStateDictionaryExtensions.cs ├── Filters │ └── NinjectScope.cs ├── Global.asax ├── Global.asax.cs ├── Orders.com.Web.Api.csproj ├── Properties │ └── AssemblyInfo.cs ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── favicon.ico └── packages.config ├── Orders.com.Web.MVC ├── App_Start │ ├── BundleConfig.cs │ ├── FilterConfig.cs │ ├── IdentityConfig.cs │ ├── NinjectWebCommon.cs │ ├── RouteConfig.cs │ └── Startup.Auth.cs ├── Configuration │ ├── DIConfig.cs │ ├── DIConfigList.cs │ ├── DIConfigSection.cs │ ├── DIConstructorArgConfig.cs │ ├── DIConstructorArgConfigList.cs │ ├── DIDefaultPropConfig.cs │ └── DIDefaultPropConfigList.cs ├── Content │ ├── Site.css │ ├── bootstrap.css │ └── bootstrap.min.css ├── Controllers │ ├── AccountController.cs │ ├── CategoriesController.cs │ ├── ControllerBase.cs │ ├── CustomersController.cs │ ├── HomeController.cs │ ├── InventoryItemsController.cs │ ├── ManageController.cs │ ├── OrderItemsController.cs │ ├── OrdersController.cs │ └── ProductsController.cs ├── DTCTransactionContext.cs ├── DependencyInjection.config ├── Global.asax ├── Global.asax.cs ├── Models │ ├── AccountViewModels.cs │ ├── IdentityModels.cs │ └── ManageViewModels.cs ├── Orders.com.Web.MVC.csproj ├── OrdersDotComDataInitializer.cs ├── Project_Readme.html ├── Properties │ └── AssemblyInfo.cs ├── Scripts │ ├── OrderItems.js │ ├── _references.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery-1.10.2.intellisense.js │ ├── jquery-1.10.2.js │ ├── jquery-1.10.2.min.js │ ├── jquery-1.10.2.min.map │ ├── jquery.validate-vsdoc.js │ ├── jquery.validate.js │ ├── jquery.validate.min.js │ ├── jquery.validate.unobtrusive.js │ ├── jquery.validate.unobtrusive.min.js │ ├── modernizr-2.6.2.js │ ├── respond.js │ └── respond.min.js ├── Startup.cs ├── ViewModels │ ├── CategoryViewModel.cs │ ├── CustomerViewModel.cs │ ├── InventoryItemViewModel.cs │ ├── OrderItemViewModel.cs │ ├── OrderViewModel.cs │ ├── ProductViewModel.cs │ └── ViewModel.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 │ ├── Categories │ │ ├── Create.cshtml │ │ ├── Delete.cshtml │ │ ├── Edit.cshtml │ │ └── Index.cshtml │ ├── Customers │ │ ├── Create.cshtml │ │ ├── Delete.cshtml │ │ ├── Edit.cshtml │ │ └── Index.cshtml │ ├── Home │ │ └── Index.cshtml │ ├── InventoryItems │ │ ├── Edit.cshtml │ │ └── Index.cshtml │ ├── Manage │ │ ├── AddPhoneNumber.cshtml │ │ ├── ChangePassword.cshtml │ │ ├── Index.cshtml │ │ ├── ManageLogins.cshtml │ │ ├── SetPassword.cshtml │ │ └── VerifyPhoneNumber.cshtml │ ├── OrderItems │ │ ├── Create.cshtml │ │ ├── Delete.cshtml │ │ └── Edit.cshtml │ ├── Orders │ │ ├── Create.cshtml │ │ ├── Delete.cshtml │ │ ├── Edit.cshtml │ │ └── Index.cshtml │ ├── Products │ │ ├── Create.cshtml │ │ ├── Delete.cshtml │ │ ├── Edit.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── Lockout.cshtml │ │ ├── _ErrorsList.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 └── packages.config ├── Orders.com.sln ├── Package.nuspec ├── README.md └── TODO.txt /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Aaron Hanusa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Orders.com.BLL.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("Orders.com.BLL.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Orders.com.BLL.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 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("c05b5c8d-0dd5-4ece-9388-e3fe79317f04")] 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 | -------------------------------------------------------------------------------- /Orders.com.BLL.Tests/Rules/CannotEditPropertyRuleTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Orders.com.BLL.Rules; 3 | using Shouldly; 4 | 5 | namespace Orders.com.BLL.Tests.Rules 6 | { 7 | [TestClass] 8 | public class CannotEditPropertyRuleTests 9 | { 10 | [TestMethod] 11 | public void Is_always_valid() 12 | { 13 | var rule = new CannotEditPropertyRule("SomeProperty"); 14 | rule.Validate().IsValid.ShouldBe(false); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Orders.com.BLL.Tests/Rules/OrderItemPriceValidityRuleTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Orders.com.BLL.Domain; 3 | using Orders.com.BLL.Rules; 4 | using Shouldly; 5 | using System.Threading.Tasks; 6 | 7 | namespace Orders.com.BLL.Tests.Rules 8 | { 9 | [TestClass] 10 | public class OrderItemPriceValidityRuleTests 11 | { 12 | [TestMethod] 13 | public void Is_valid_when_item_price_equals_product_price() 14 | { 15 | var orderItem = new OrderItem() { Price = 10 }; 16 | var product = new Product { Price = 10 }; 17 | var rule = new OrderItemPriceValidityRule(orderItem, product); 18 | rule.Validate().IsValid.ShouldBe(true); 19 | rule.ErrorMessage.ShouldBe(null); 20 | } 21 | 22 | [TestMethod] 23 | public void Is_invalid_when_item_price_does_not_equal_product_price() 24 | { 25 | var orderItem = new OrderItem() { Price = 10 }; 26 | var product = new Product { Price = 11 }; 27 | var rule = new OrderItemPriceValidityRule(orderItem, product); 28 | rule.Validate().IsValid.ShouldBe(false); 29 | rule.ErrorMessage.ShouldNotBe(null); 30 | } 31 | 32 | [TestMethod] 33 | public async Task Is_valid_when_item_price_equals_product_price_async() 34 | { 35 | var orderItem = new OrderItem() { Price = 10 }; 36 | var product = new Product { Price = 10 }; 37 | var rule = new OrderItemPriceValidityRule(orderItem, product); 38 | await rule.ValidateAsync(); 39 | rule.IsValid.ShouldBe(true); 40 | rule.ErrorMessage.ShouldBe(null); 41 | } 42 | 43 | [TestMethod] 44 | public async Task Is_invalid_when_item_price_does_not_equal_product_price_async() 45 | { 46 | var orderItem = new OrderItem() { Price = 10 }; 47 | var product = new Product { Price = 11 }; 48 | var rule = new OrderItemPriceValidityRule(orderItem, product); 49 | await rule.ValidateAsync(); 50 | rule.IsValid.ShouldBe(false); 51 | rule.ErrorMessage.ShouldNotBe(null); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Orders.com.BLL.Tests/Rules/ValidOrderItemStatusForDeleteRuleTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using Orders.com.BLL.Domain; 3 | using Orders.com.BLL.Extensions; 4 | using Orders.com.BLL.Rules; 5 | using Shouldly; 6 | using System.Threading.Tasks; 7 | 8 | namespace Orders.com.BLL.Tests.Rules 9 | { 10 | [TestClass] 11 | public class ValidOrderItemStatusForDeleteRuleTests 12 | { 13 | [TestMethod] 14 | public void Is_valid_when_item_status_is_not_shipped() 15 | { 16 | var item = new OrderItem(); 17 | item.OrderStatusID = OrderStatusConstants.PENDING_STATUS; 18 | var rule = new ValidOrderItemStatusForDeleteRule(item); 19 | rule.Validate().IsValid.ShouldBe(true); 20 | rule.ErrorMessage.ShouldBe(null); 21 | } 22 | 23 | [TestMethod] 24 | public void Is_invalid_when_item_status_is_shipped() 25 | { 26 | var item = new OrderItem(); 27 | item.OrderStatusID = OrderStatusConstants.SHIPPED_STATUS; 28 | var rule = new ValidOrderItemStatusForDeleteRule(item); 29 | rule.Validate().IsValid.ShouldBe(false); 30 | rule.ErrorMessage.ShouldNotBe(null); 31 | } 32 | 33 | [TestMethod] 34 | public async Task Is_valid_when_item_status_is_not_shipped_async() 35 | { 36 | var item = new OrderItem(); 37 | item.OrderStatusID = OrderStatusConstants.PENDING_STATUS; 38 | var rule = new ValidOrderItemStatusForDeleteRule(item); 39 | await rule.ValidateAsync(); 40 | rule.IsValid.ShouldBe(true); 41 | rule.ErrorMessage.ShouldBe(null); 42 | } 43 | 44 | [TestMethod] 45 | public async Task Is_invalid_when_item_status_is_shipped_async() 46 | { 47 | var item = new OrderItem(); 48 | item.OrderStatusID = OrderStatusConstants.SHIPPED_STATUS; 49 | var rule = new ValidOrderItemStatusForDeleteRule(item); 50 | await rule.ValidateAsync(); 51 | rule.IsValid.ShouldBe(false); 52 | rule.ErrorMessage.ShouldNotBe(null); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Orders.com.BLL.Tests/TransactionContextStub.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Orders.com.BLL.Tests 9 | { 10 | public class TransactionContextStub : ITransactionContext 11 | { 12 | public void Execute(Action codeToRunWithinTransaction) 13 | { 14 | codeToRunWithinTransaction(); 15 | } 16 | 17 | public T Execute(Func codeToRunWithinTransaction) 18 | { 19 | return codeToRunWithinTransaction(); 20 | } 21 | 22 | public async Task ExecuteAsync(Func codeToRunWithinTransaction) 23 | { 24 | await codeToRunWithinTransaction(); 25 | } 26 | 27 | public async Task ExecuteAsync(Func> codeToRunWithinTransaction) 28 | { 29 | return await codeToRunWithinTransaction(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Orders.com.BLL.Tests/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Orders.com.BLL.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Orders.com.BLL/DataProxy/ICategoryDataProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | 3 | namespace Orders.com.BLL.DataProxy 4 | { 5 | public interface ICategoryDataProxy : IOrdersDotComDataProxy 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Orders.com.BLL/DataProxy/ICustomerDataProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | 3 | namespace Orders.com.BLL.DataProxy 4 | { 5 | public interface ICustomerDataProxy : IOrdersDotComDataProxy 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Orders.com.BLL/DataProxy/IOrderDataProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.QueryData; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Orders.com.BLL.DataProxy 7 | { 8 | public interface IOrderDataProxy : IOrdersDotComDataProxy 9 | { 10 | IEnumerable GetAll(int start, int pageSize); 11 | Task> GetAllAsync(int start, int pageSize); 12 | IEnumerable GetByCustomer(long customerID); 13 | Task> GetByCustomerAsync(long customerID); 14 | IEnumerable GetByProduct(long productID); 15 | Task> GetByProductAsync(long productID); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Orders.com.BLL/DataProxy/IOrderItemDataProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace Orders.com.BLL.DataProxy 6 | { 7 | public interface IOrderItemDataProxy : IOrdersDotComDataProxy 8 | { 9 | IEnumerable GetByOrder(long orderID); 10 | Task> GetByOrderAsync(long orderID); 11 | OrderItem Submit(OrderItem orderItem); 12 | Task SubmitAsync(OrderItem orderItem); 13 | OrderItem Ship(OrderItem orderItem); 14 | Task ShipAsync(OrderItem orderItem); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Orders.com.BLL/DataProxy/IOrderStatusDataProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | 3 | namespace Orders.com.BLL.DataProxy 4 | { 5 | public interface IOrderStatusDataProxy : IOrdersDotComDataProxy 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Orders.com.BLL/DataProxy/IOrdersDotComDataProxy.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | 3 | namespace Orders.com.BLL.DataProxy 4 | { 5 | public interface IOrdersDotComDataProxy : IServiceDataProxy 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Orders.com.BLL/DataProxy/IProductDataProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace Orders.com.BLL.DataProxy 6 | { 7 | public interface IProductDataProxy : IOrdersDotComDataProxy 8 | { 9 | IEnumerable GetByCategory(long categoryID); 10 | Task> GetByCategoryAsync(long categoryID); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Orders.com.BLL/DataProxy/InventoryItemDataProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using System.Threading.Tasks; 3 | 4 | namespace Orders.com.BLL.DataProxy 5 | { 6 | public interface IInventoryItemDataProxy : IOrdersDotComDataProxy 7 | { 8 | InventoryItem GetByProduct(long productID); 9 | Task GetByProductAsync(long productID); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/Category.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Orders.com.BLL.Domain 4 | { 5 | public class Category : DomainBase 6 | { 7 | public long CategoryID { get; set; } 8 | 9 | [Required] 10 | public string Name { get; set; } 11 | 12 | public override long ID 13 | { 14 | get { return CategoryID; } 15 | set { CategoryID = value; } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/Customer.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Orders.com.BLL.Domain 4 | { 5 | public class Customer : DomainBase 6 | { 7 | public long CustomerID { get; set; } 8 | 9 | [Required] 10 | [StringLength(20)] 11 | public string Name { get; set; } 12 | 13 | public override long ID 14 | { 15 | set { CustomerID = value; } 16 | get { return CustomerID; } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/DomainBase.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using System; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Runtime.Serialization; 5 | //using Newtonsoft.Json; 6 | 7 | namespace Orders.com.BLL.Domain 8 | { 9 | public abstract class DomainBase : IDomainObject 10 | { 11 | // TODO: Include Newtonsoft.json?? 12 | //[JsonIgnore, IgnoreDataMember] 13 | public abstract long ID { get; set; } 14 | 15 | public string Self { get; set; } 16 | 17 | [Editable(false)] 18 | public int? CreatedBy { get; set; } 19 | 20 | [Editable(false)] 21 | public DateTime CreatedDatetime { get; set; } 22 | 23 | [Editable(false)] 24 | public int? LastModifiedBy { get; set; } 25 | 26 | [Editable(false)] 27 | public DateTime? LastModifiedDatetime { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/IOrderStatusIDContainer.cs: -------------------------------------------------------------------------------- 1 | namespace Orders.com.BLL.Domain 2 | { 3 | public interface IOrderStatusIDContainer 4 | { 5 | long OrderStatusID { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/InventoryItem.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Orders.com.BLL.Domain 5 | { 6 | public class InventoryItem : DomainBase, IVersionContainer 7 | { 8 | public long InventoryItemID { get; set; } 9 | 10 | [Range(0, double.MaxValue, ErrorMessage = "Quantity on Hand must be a non-negative value")] 11 | [Display(Name = "Quantity on Hand")] 12 | public decimal QuantityOnHand { get; set; } 13 | 14 | public long ProductID { get; set; } 15 | 16 | public override long ID 17 | { 18 | get { return InventoryItemID; } 19 | set { InventoryItemID = value; } 20 | } 21 | 22 | [Editable(false)] 23 | public string Version 24 | { 25 | get; set; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/Order.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using Peasy.Attributes; 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Orders.com.BLL.Domain 7 | { 8 | public class Order : DomainBase 9 | { 10 | public long OrderID { get; set; } 11 | 12 | [PeasyForeignKey, PeasyRequired] 13 | public long CustomerID { get; set; } 14 | 15 | [Editable(false)] 16 | public DateTime OrderDate { get; set; } 17 | 18 | public override long ID 19 | { 20 | get { return OrderID; } 21 | set { OrderID = value; } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/OrderItem.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using Peasy.Attributes; 3 | using System.ComponentModel.DataAnnotations; 4 | using System; 5 | 6 | namespace Orders.com.BLL.Domain 7 | { 8 | public class OrderItem : DomainBase, IOrderStatusIDContainer 9 | { 10 | public long OrderItemID { get; set; } 11 | 12 | [PeasyForeignKey, PeasyRequired] 13 | public long OrderID { get; set; } 14 | 15 | [PeasyForeignKey, PeasyRequired, Editable(false)] 16 | public long ProductID { get; set; } 17 | 18 | [Range(1, double.MaxValue, ErrorMessage = "Quantity must be greater than 0")] 19 | public decimal Quantity { get; set; } 20 | 21 | public decimal Amount { get; set; } 22 | 23 | public decimal Price { get; set; } 24 | 25 | [Editable(false)] 26 | public DateTime? BackorderedDate { get; set; } 27 | 28 | [Editable(false)] 29 | public DateTime? ShippedDate { get; set; } 30 | 31 | [Editable(false)] 32 | public DateTime? SubmittedDate { get; set; } 33 | 34 | [Editable(false)] 35 | public long OrderStatusID { get; set; } 36 | 37 | public override long ID 38 | { 39 | get { return OrderItemID; } 40 | set { OrderItemID = value; } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/OrderStatus.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Orders.com.BLL.Domain 3 | { 4 | public class OrderStatus : DomainBase 5 | { 6 | public long OrderStatusID { get; set; } 7 | 8 | public string Name { get; set; } 9 | 10 | public override long ID 11 | { 12 | get { return OrderStatusID; } 13 | set { OrderStatusID = value; } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Orders.com.BLL/Domain/Product.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using Peasy.Attributes; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Orders.com.BLL.Domain 6 | { 7 | public class Product : DomainBase 8 | { 9 | public long ProductID { get; set; } 10 | 11 | [Required] 12 | [StringLength(30)] 13 | public string Name { get; set; } 14 | 15 | public string Description { get; set; } 16 | 17 | [Required] 18 | public decimal? Price { get; set; } 19 | 20 | [PeasyForeignKey, PeasyRequired, Display(Name="Category")] 21 | public long CategoryID { get; set; } 22 | 23 | public override long ID 24 | { 25 | get { return ProductID; } 26 | set { ProductID = value; } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Orders.com.BLL/Extensions/IVersionContainerExtensions.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using System; 3 | 4 | namespace Orders.com.BLL.Extensions 5 | { 6 | public static class IVersionContainerExtensions 7 | { 8 | public static IVersionContainer IncrementVersionByOne(this IVersionContainer container) 9 | { 10 | container.Version = (Convert.ToInt64(container.Version) + 1).ToString(); 11 | return container; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Orders.com.BLL/Extensions/OrderItemExtensions.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using System; 3 | 4 | namespace Orders.com.BLL.Extensions 5 | { 6 | public static class OrderItemExtensions 7 | { 8 | public static Tuple SetPrice(this OrderItem item, decimal price) 9 | { 10 | item.Price = price; 11 | return new Tuple(item); 12 | } 13 | 14 | public static OrderItem SetAmount(this OrderItem item) 15 | { 16 | item.Amount = item.Quantity * item.Price; 17 | return item; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Orders.com.BLL/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Resources; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Orders.com.BLL")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Orders.com.BLL")] 14 | [assembly: AssemblyCopyright("Copyright © 2015")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: NeutralResourcesLanguage("en")] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | -------------------------------------------------------------------------------- /Orders.com.BLL/QueryData/OrderInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Orders.com.BLL.QueryData 5 | { 6 | public class OrderInfo 7 | { 8 | public long OrderID { get; set; } 9 | [Display(Name ="Order Date")] 10 | public DateTime OrderDate { get; set; } 11 | [Display(Name ="Customer")] 12 | public string CustomerName { get; set; } 13 | public long CustomerID { get; set; } 14 | [DisplayFormat(DataFormatString = "{0:c}")] 15 | public decimal Total { get; set; } 16 | public string Status { get; set; } 17 | public bool HasShippedItems { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/CanDeleteCategoryRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Peasy; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Orders.com.BLL.Rules 7 | { 8 | public class CanDeleteCategoryRule : RuleBase 9 | { 10 | private long _categoryID; 11 | private IProductDataProxy _productsDataProxy; 12 | 13 | public CanDeleteCategoryRule(long categoryID, IProductDataProxy productsDataProxy) 14 | { 15 | _categoryID = categoryID; 16 | _productsDataProxy = productsDataProxy; 17 | } 18 | 19 | protected override void OnValidate() 20 | { 21 | var products = _productsDataProxy.GetByCategory(_categoryID); 22 | if (products.Any()) 23 | { 24 | Invalidate("This category is associated with one or more products and cannot be deleted."); 25 | } 26 | } 27 | 28 | protected override async Task OnValidateAsync() 29 | { 30 | var products = await _productsDataProxy.GetByCategoryAsync(_categoryID); 31 | if (products.Any()) 32 | { 33 | Invalidate("This category is associated with one or more products and cannot be deleted."); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/CanDeleteCustomerRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Services; 2 | using Peasy; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Orders.com.BLL.Rules 7 | { 8 | public class CanDeleteCustomerRule : RuleBase 9 | { 10 | private long _customerID; 11 | private IOrderService _orderService; 12 | 13 | public CanDeleteCustomerRule(long customerID, IOrderService orderService) 14 | { 15 | _customerID = customerID; 16 | _orderService = orderService; 17 | } 18 | 19 | protected override void OnValidate() 20 | { 21 | var orders = _orderService.GetByCustomerCommand(_customerID).Execute().Value; 22 | if (orders.Any()) 23 | { 24 | Invalidate("This customer is associated with one or more orders and cannot be deleted."); 25 | } 26 | } 27 | 28 | protected override async Task OnValidateAsync() 29 | { 30 | var orders = await _orderService.GetByCustomerCommand(_customerID).ExecuteAsync(); 31 | if (orders.Value.Any()) 32 | { 33 | Invalidate("This customer is associated with one or more orders and cannot be deleted."); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/CanDeleteProductRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Peasy; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Orders.com.BLL.Rules 7 | { 8 | public class CanDeleteProductRule : RuleBase 9 | { 10 | private long _productID; 11 | private string _errorMessage = "This product is associated with one or more orders and cannot be deleted."; 12 | private IOrderDataProxy _ordersDataProxy; 13 | 14 | public CanDeleteProductRule(long productID, IOrderDataProxy ordersDataProxy) 15 | { 16 | _productID = productID; 17 | _ordersDataProxy = ordersDataProxy; 18 | } 19 | 20 | protected override void OnValidate() 21 | { 22 | var orders = _ordersDataProxy.GetByProduct(_productID); 23 | if (orders.Any()) 24 | { 25 | Invalidate(_errorMessage); 26 | } 27 | } 28 | 29 | protected override async Task OnValidateAsync() 30 | { 31 | var orders = await _ordersDataProxy.GetByProductAsync(_productID); 32 | if (orders.Any()) 33 | { 34 | Invalidate(_errorMessage); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/CanShipOrderItemRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Extensions; 3 | using Peasy; 4 | 5 | namespace Orders.com.BLL.Rules 6 | { 7 | public class CanShipOrderItemRule : RuleBase 8 | { 9 | private OrderItem _orderItem; 10 | 11 | public CanShipOrderItemRule(OrderItem orderItem) 12 | { 13 | _orderItem = orderItem; 14 | } 15 | 16 | protected override void OnValidate() 17 | { 18 | if (!_orderItem.OrderStatus().CanShip) 19 | { 20 | Invalidate(string.Format("Order Item ID {0} is in a {1} state and cannot be shipped", _orderItem.ID.ToString(), _orderItem.OrderStatus().Name)); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/CanSubmitOrderItemRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Extensions; 3 | using Peasy; 4 | 5 | namespace Orders.com.BLL.Rules 6 | { 7 | public class CanSubmitOrderItemRule : RuleBase 8 | { 9 | private OrderItem _orderItem; 10 | 11 | public CanSubmitOrderItemRule(OrderItem orderItem) 12 | { 13 | _orderItem = orderItem; 14 | } 15 | 16 | protected override void OnValidate() 17 | { 18 | if (!_orderItem.OrderStatus().CanSubmit) 19 | { 20 | Invalidate(string.Format("Order Item ID:{0} is in a {1} state and cannot be submitted", _orderItem .ID.ToString(), _orderItem .OrderStatus().Name)); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/CannotEditPropertyRule.cs: -------------------------------------------------------------------------------- 1 | using Peasy.Extensions; 2 | using System; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | using System.Threading.Tasks; 7 | using Orders.com.BLL.Domain; 8 | using Peasy; 9 | 10 | namespace Orders.com.BLL.Rules 11 | { 12 | public class CannotEditPropertyRule : RuleBase 13 | { 14 | private string _propertyName; 15 | 16 | public CannotEditPropertyRule(string propertyName) 17 | { 18 | _propertyName = propertyName; 19 | } 20 | 21 | protected override void OnValidate() 22 | { 23 | Invalidate(string.Format("{0} cannot be changed.", _propertyName)); 24 | } 25 | 26 | protected override Task OnValidateAsync() 27 | { 28 | return Task.Run(() => OnValidate()); 29 | } 30 | } 31 | 32 | public class CannotEditPropertyRule : RuleBase where T : DomainBase 33 | { 34 | private T _original; 35 | private T _changed; 36 | private Expression> _propertyExpression; 37 | 38 | public CannotEditPropertyRule(T original, T changed, Expression> propertyExpression) 39 | { 40 | _original = original; 41 | _changed = changed; 42 | _propertyExpression = propertyExpression; 43 | } 44 | 45 | protected override void OnValidate() 46 | { 47 | var propertyName = ExpressionExtensions.ExtractPropertyName(_propertyExpression); 48 | var originalType = typeof(T); 49 | var property = originalType.GetTypeInfo().DeclaredProperties.First(p => p.Name == propertyName); 50 | var originalValue = property.GetValue(_original); 51 | var changedValue = property.GetValue(_changed); 52 | if (originalValue != changedValue) 53 | { 54 | Invalidate(string.Format("{0} cannot be changed.", propertyName)); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/OrderItemAmountValidityRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Peasy; 3 | 4 | namespace Orders.com.BLL.Rules 5 | { 6 | public class OrderItemAmountValidityRule : RuleBase 7 | { 8 | private OrderItem _item; 9 | private Product _product; 10 | 11 | public OrderItemAmountValidityRule(OrderItem item, Product product) 12 | { 13 | _item = item; 14 | _product = product; 15 | } 16 | 17 | protected override void OnValidate() 18 | { 19 | if (_item.Amount != _product.Price * _item.Quantity) 20 | { 21 | Invalidate(string.Format("The amount for {0} does not match the specified quantity multiplied by the current price in our system", _product.Name)); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/OrderItemPriceValidityRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Peasy; 3 | 4 | namespace Orders.com.BLL.Rules 5 | { 6 | public class OrderItemPriceValidityRule : RuleBase 7 | { 8 | private OrderItem _item; 9 | private Product _product; 10 | 11 | public OrderItemPriceValidityRule(OrderItem item, Product product) 12 | { 13 | _item = item; 14 | _product = product; 15 | } 16 | 17 | protected override void OnValidate() 18 | { 19 | if (_item.Price != _product.Price) 20 | { 21 | Invalidate(string.Format("The price for {0} no longer reflects the current price in our system", _product.Name)); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/ValidOrderItemStatusForDeleteRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Extensions; 3 | using Peasy; 4 | 5 | namespace Orders.com.BLL.Rules 6 | { 7 | public class ValidOrderItemStatusForDeleteRule : RuleBase 8 | { 9 | private OrderItem _item; 10 | 11 | public ValidOrderItemStatusForDeleteRule(OrderItem item) 12 | { 13 | _item = item; 14 | } 15 | 16 | protected override void OnValidate() 17 | { 18 | if (_item.OrderStatus().IsShipped) 19 | { 20 | Invalidate("Shipped items cannot be deleted"); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/ValidOrderItemStatusForUpdateRule.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Extensions; 3 | using Peasy; 4 | 5 | namespace Orders.com.BLL.Rules 6 | { 7 | public class ValidOrderItemStatusForUpdateRule : RuleBase 8 | { 9 | private OrderItem _item; 10 | 11 | public ValidOrderItemStatusForUpdateRule(OrderItem item) 12 | { 13 | _item = item; 14 | } 15 | 16 | protected override void OnValidate() 17 | { 18 | if (_item.OrderStatus().IsBackordered) 19 | { 20 | Invalidate("Backordered items cannot be changed"); 21 | } 22 | else if (_item.OrderStatus().IsShipped) 23 | { 24 | Invalidate("Shipped items cannot be changed"); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Orders.com.BLL/Rules/ValidOrderStatusForUpdateRule.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using Orders.com.BLL.Services; 4 | using Orders.com.BLL.Extensions; 5 | using Peasy; 6 | 7 | namespace Orders.com.BLL.Rules 8 | { 9 | public class ValidOrderStatusForUpdateRule : RuleBase 10 | { 11 | private long _orderID; 12 | private IOrderItemService _orderItemDataProxy; 13 | 14 | public ValidOrderStatusForUpdateRule(long orderID, IOrderItemService orderItemDataProxy) 15 | { 16 | _orderID = orderID; 17 | _orderItemDataProxy = orderItemDataProxy; 18 | } 19 | 20 | protected override void OnValidate() 21 | { 22 | var items = _orderItemDataProxy.GetByOrderCommand(_orderID).Execute().Value; 23 | if (items.Any(i => i.OrderStatus() is ShippedState)) 24 | { 25 | Invalidate("This order cannot change because it has items that have been shipped"); 26 | } 27 | } 28 | 29 | protected override async Task OnValidateAsync() 30 | { 31 | var items = await _orderItemDataProxy.GetByOrderCommand(_orderID).ExecuteAsync(); 32 | if (items.Value.Any(i => i.OrderStatus() is ShippedState)) 33 | { 34 | Invalidate("This order cannot change because it has items that have been shipped"); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/CategoryService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Orders.com.BLL.Rules; 3 | using System.Threading.Tasks; 4 | using Orders.com.BLL.Domain; 5 | using Orders.com.BLL.DataProxy; 6 | using Peasy; 7 | 8 | namespace Orders.com.BLL.Services 9 | { 10 | public class CategoryService : OrdersDotComServiceBase, ICategoryService 11 | { 12 | private IProductDataProxy _productsDataProxy; 13 | 14 | public CategoryService(ICategoryDataProxy dataProxy, IProductDataProxy productsDataProxy) : base(dataProxy) 15 | { 16 | _productsDataProxy = productsDataProxy; 17 | } 18 | 19 | protected override IEnumerable GetBusinessRulesForDelete(long id, ExecutionContext context) 20 | { 21 | yield return base.GetBusinessRulesForDelete(id, context) 22 | .IfAllValidThenValidate 23 | ( 24 | new CanDeleteCategoryRule(id, _productsDataProxy) 25 | ); 26 | } 27 | 28 | protected override async Task> GetBusinessRulesForDeleteAsync(long id, ExecutionContext context) 29 | { 30 | var baseRules = await base.GetBusinessRulesForDeleteAsync(id, context); 31 | return baseRules.IfAllValidThenValidate(new CanDeleteCategoryRule(id, _productsDataProxy)) 32 | .ToArray(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/CustomerService.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Rules; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Orders.com.BLL.Domain; 5 | using Orders.com.BLL.DataProxy; 6 | using Peasy; 7 | 8 | namespace Orders.com.BLL.Services 9 | { 10 | public class CustomerService : OrdersDotComServiceBase, ICustomerService 11 | { 12 | private IOrderService _orderService; 13 | 14 | public CustomerService(ICustomerDataProxy dataProxy, IOrderService orderService) : base(dataProxy) 15 | { 16 | _orderService = orderService; 17 | } 18 | 19 | protected override IEnumerable GetBusinessRulesForDelete(long id, ExecutionContext context) 20 | { 21 | yield return base.GetBusinessRulesForDelete(id, context) 22 | .IfAllValidThenValidate 23 | ( 24 | new CanDeleteCustomerRule(id, _orderService) 25 | ); 26 | } 27 | 28 | protected override async Task> GetBusinessRulesForDeleteAsync(long id, ExecutionContext context) 29 | { 30 | var baseRules = await base.GetBusinessRulesForDeleteAsync(id, context); 31 | return baseRules.IfAllValidThenValidate(new CanDeleteCustomerRule(id, _orderService)) 32 | .ToArray(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/ICategoryService.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Peasy; 3 | 4 | namespace Orders.com.BLL.Services 5 | { 6 | public interface ICategoryService : IService 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/ICustomerService.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Peasy; 3 | 4 | namespace Orders.com.BLL.Services 5 | { 6 | public interface ICustomerService : IService 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/IInventoryItemService.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Peasy; 3 | 4 | namespace Orders.com.BLL.Services 5 | { 6 | public interface IInventoryItemService : IService 7 | { 8 | ICommand GetByProductCommand(long productID); 9 | } 10 | } -------------------------------------------------------------------------------- /Orders.com.BLL/Services/IOrderItemService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Orders.com.BLL.Domain; 3 | using Peasy; 4 | 5 | namespace Orders.com.BLL.Services 6 | { 7 | public interface IOrderItemService : IService 8 | { 9 | ICommand> GetByOrderCommand(long orderID); 10 | ICommand ShipCommand(long orderItemID); 11 | ICommand SubmitCommand(long orderItemID); 12 | } 13 | } -------------------------------------------------------------------------------- /Orders.com.BLL/Services/IOrderService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Orders.com.BLL.Domain; 3 | using Orders.com.BLL.QueryData; 4 | using Peasy; 5 | 6 | namespace Orders.com.BLL.Services 7 | { 8 | public interface IOrderService : IService 9 | { 10 | ICommand> GetAllCommand(int start, int pageSize); 11 | ICommand> GetByCustomerCommand(long customerID); 12 | ICommand> GetByProductCommand(long productID); 13 | } 14 | } -------------------------------------------------------------------------------- /Orders.com.BLL/Services/IOrderStatusService.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Peasy; 3 | 4 | namespace Orders.com.BLL.Services 5 | { 6 | public interface IOrderStatusService : IService 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/IProductService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Orders.com.BLL.Domain; 3 | using Peasy; 4 | 5 | namespace Orders.com.BLL.Services 6 | { 7 | public interface IProductService : IService 8 | { 9 | ICommand> GetByCategoryCommand(long categoryID); 10 | } 11 | } -------------------------------------------------------------------------------- /Orders.com.BLL/Services/IntentoryItemService.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.DataProxy; 3 | using Peasy; 4 | 5 | namespace Orders.com.BLL.Services 6 | { 7 | public class InventoryItemService : OrdersDotComServiceBase, IInventoryItemService 8 | { 9 | public InventoryItemService(IInventoryItemDataProxy dataProxy) : base(dataProxy) 10 | { 11 | } 12 | 13 | public ICommand GetByProductCommand(long productID) 14 | { 15 | var proxy = DataProxy as IInventoryItemDataProxy; 16 | return new ServiceCommand 17 | ( 18 | executeMethod: () => proxy.GetByProduct(productID), 19 | executeAsyncMethod: () => proxy.GetByProductAsync(productID) 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/OrderItemClientService.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using Orders.com.BLL.DataProxy; 3 | using Orders.com.BLL.Domain; 4 | 5 | namespace Orders.com.BLL.Services 6 | { 7 | public class OrderItemClientService : OrderItemService 8 | { 9 | private ITransactionContext _transactionContext; 10 | private IInventoryItemDataProxy _inventoryDataProxy; 11 | 12 | public OrderItemClientService(IOrderItemDataProxy dataProxy, 13 | IProductDataProxy productDataProxy, 14 | IInventoryItemDataProxy inventoryDataProxy, 15 | ITransactionContext transactionContext) : base(dataProxy, productDataProxy, inventoryDataProxy, transactionContext) 16 | { 17 | _inventoryDataProxy = inventoryDataProxy; 18 | _transactionContext = transactionContext; 19 | } 20 | 21 | public override ICommand ShipCommand(long orderItemID) 22 | { 23 | var proxy = DataProxy as IOrderItemDataProxy; 24 | return new ServiceCommand 25 | ( 26 | executeMethod: () => { return proxy.Ship(new OrderItem { OrderItemID = orderItemID }); }, 27 | executeAsyncMethod: () => { return proxy.ShipAsync(new OrderItem { OrderItemID = orderItemID }); } 28 | ); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/OrderStatusService.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | 4 | namespace Orders.com.BLL.Services 5 | { 6 | public class OrderStatusService : OrdersDotComServiceBase, IOrderStatusService 7 | { 8 | public OrderStatusService(IOrderStatusDataProxy dataProxy) : base(dataProxy) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/ProductClientService.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using Orders.com.BLL.DataProxy; 3 | using Orders.com.BLL.Domain; 4 | 5 | namespace Orders.com.BLL.Services 6 | { 7 | public class ProductClientService : ProductService, IProductService 8 | { 9 | public ProductClientService(IProductDataProxy dataProxy, IOrderDataProxy orderDataProxy, IInventoryItemService inventoryService, ITransactionContext transactionContext) : base(dataProxy, orderDataProxy, inventoryService, transactionContext) 10 | { 11 | } 12 | 13 | public override ICommand InsertCommand(Product entity) 14 | { 15 | var dataProxy = DataProxy as IProductDataProxy; 16 | return new ServiceCommand 17 | ( 18 | executeMethod: () => dataProxy.Insert(entity), 19 | executeAsyncMethod: () => dataProxy.InsertAsync(entity) 20 | ); 21 | } 22 | 23 | public override ICommand DeleteCommand(long id) 24 | { 25 | var dataProxy = DataProxy as IProductDataProxy; 26 | return new ServiceCommand 27 | ( 28 | executeMethod: () => dataProxy.Delete(id), 29 | executeAsyncMethod: () => dataProxy.DeleteAsync(id) 30 | ); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Orders.com.BLL/Services/ProductService.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using Orders.com.BLL.Commands; 3 | using System.Collections.Generic; 4 | using Orders.com.BLL.Domain; 5 | using Orders.com.BLL.DataProxy; 6 | 7 | namespace Orders.com.BLL.Services 8 | { 9 | public class ProductService : OrdersDotComServiceBase, IProductService 10 | { 11 | private IInventoryItemService _inventoryService; 12 | private ITransactionContext _transactionContext; 13 | private IOrderDataProxy _orderDataProxy; 14 | 15 | public ProductService(IProductDataProxy dataProxy, IOrderDataProxy orderDataProxy, IInventoryItemService inventoryService, ITransactionContext transactionContext) : base(dataProxy) 16 | { 17 | _orderDataProxy = orderDataProxy; 18 | _inventoryService = inventoryService; 19 | _transactionContext = transactionContext; 20 | } 21 | 22 | public override ICommand InsertCommand(Product entity) 23 | { 24 | var dataProxy = DataProxy as IProductDataProxy; 25 | return new CreateProductCommand(entity, dataProxy, _inventoryService, _transactionContext); 26 | } 27 | 28 | public ICommand> GetByCategoryCommand(long categoryID) 29 | { 30 | var dataProxy = DataProxy as IProductDataProxy; 31 | return new ServiceCommand> 32 | ( 33 | executeMethod: () => dataProxy.GetByCategory(categoryID), 34 | executeAsyncMethod: () => dataProxy.GetByCategoryAsync(categoryID) 35 | ); 36 | } 37 | 38 | public override ICommand DeleteCommand(long id) 39 | { 40 | var dataProxy = DataProxy as IProductDataProxy; 41 | return new DeleteProductCommand(id, dataProxy, _inventoryService, _orderDataProxy, _transactionContext); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Orders.com.BLL/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "supports": {}, 3 | "dependencies": { 4 | "AutoMapper": "6.1.0", 5 | "Microsoft.NETCore.Portable.Compatibility": "1.0.1", 6 | "NETStandard.Library": "1.6.0", 7 | "Peasy": "2.0.2" 8 | }, 9 | "frameworks": { 10 | "netstandard1.1": {} 11 | } 12 | } -------------------------------------------------------------------------------- /Orders.com.DAL.EF/App.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 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/CategoryRepository.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | 4 | namespace Orders.com.DAL.EF 5 | { 6 | public class CategoryRepository : OrdersDotComRepositoryBase, ICategoryDataProxy 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/CustomerRepository.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.DataProxy; 3 | 4 | namespace Orders.com.DAL.EF 5 | { 6 | public class CustomerRepository : OrdersDotComRepositoryBase, ICustomerDataProxy 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/InventoryItemRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using System.Data.Entity; 4 | using Peasy.Exception; 5 | using Orders.com.BLL.Domain; 6 | using Orders.com.BLL.DataProxy; 7 | using Orders.com.BLL.Extensions; 8 | 9 | namespace Orders.com.DAL.EF 10 | { 11 | public class InventoryItemRepository : OrdersDotComRepositoryBase, IInventoryItemDataProxy 12 | { 13 | public InventoryItem GetByProduct(long productID) 14 | { 15 | using (var context = GetDbContext()) 16 | { 17 | return context.Set().First(i => i.ProductID == productID); 18 | } 19 | } 20 | 21 | public async Task GetByProductAsync(long productID) 22 | { 23 | using (var context = GetDbContext()) 24 | { 25 | var items = await context.Set().Where(i => i.ProductID == productID).ToListAsync(); 26 | return items.First(); 27 | } 28 | } 29 | 30 | protected override void OnBeforeUpdateExecuted(DbContext context, InventoryItem entity) 31 | { 32 | var existing = context.Set() 33 | .FirstOrDefault(e => e.ID.Equals(entity.ID) && e.Version == entity.Version); 34 | if (existing == null) 35 | throw new ConcurrencyException($"{entity.GetType().Name} with id {entity.ID.ToString()} was already changed"); 36 | 37 | entity.IncrementVersionByOne(); 38 | } 39 | 40 | protected override async Task OnBeforeUpdateExecutedAsync(DbContext context, InventoryItem entity) 41 | { 42 | var existing = await context.Set() 43 | .FirstOrDefaultAsync(e => e.ID.Equals(entity.ID) && e.Version == entity.Version); 44 | if (existing == null) 45 | throw new ConcurrencyException($"{entity.GetType().Name} with id {entity.ID.ToString()} was already changed"); 46 | 47 | entity.IncrementVersionByOne(); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Orders.com.DAL.EF/MapsterHelper.cs: -------------------------------------------------------------------------------- 1 | using Mapster; 2 | using Peasy.DataProxy.EF6; 3 | 4 | namespace Orders.com.DAL.EF 5 | { 6 | public class MapsterHelper : IMapper 7 | { 8 | public TDestination Map(TSource source) 9 | { 10 | return TypeAdapter.Adapt(source); 11 | } 12 | 13 | public TDestination Map(TSource source, TDestination destination) 14 | { 15 | return TypeAdapter.Adapt(source, destination); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/Migrations/201511301846134_Initial.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Orders.com.DAL.EF.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.1.3-40302")] 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 "201511301846134_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 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/Migrations/Configuration.cs: -------------------------------------------------------------------------------- 1 | namespace Orders.com.DAL.EF.Migrations 2 | { 3 | using BLL.Domain; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Data.Entity.Migrations; 7 | 8 | public sealed class Configuration : DbMigrationsConfiguration 9 | { 10 | public Configuration() 11 | { 12 | AutomaticMigrationsEnabled = false; 13 | } 14 | 15 | protected override void Seed(Orders.com.DAL.EF.OrdersDotComContext context) 16 | { 17 | var customers = new List 18 | { 19 | new Customer { Name = "Jimi Hendrix", CreatedDatetime = DateTime.Now }, 20 | new Customer { Name = "David Gilmour", CreatedDatetime = DateTime.Now }, 21 | new Customer { Name = "James Page", CreatedDatetime = DateTime.Now } 22 | }; 23 | 24 | customers.ForEach(s => context.Customers.Add(s)); 25 | context.SaveChanges(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/OrderItemRepository.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | using System.Collections.Generic; 4 | using System.Data.Entity; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using Peasy; 8 | 9 | namespace Orders.com.DAL.EF 10 | { 11 | public class OrderItemRepository : OrdersDotComRepositoryBase, IOrderItemDataProxy 12 | { 13 | public IEnumerable GetByOrder(long orderID) 14 | { 15 | using (var context = GetDbContext()) 16 | { 17 | return context.Set().Where(i => i.OrderID == orderID).ToArray(); 18 | } 19 | } 20 | 21 | public async Task> GetByOrderAsync(long orderID) 22 | { 23 | using (var context = GetDbContext()) 24 | { 25 | var items = await context.Set().Where(i => i.OrderID == orderID).ToListAsync(); 26 | return items; 27 | } 28 | } 29 | 30 | public OrderItem Ship(OrderItem orderItem) 31 | { 32 | return base.Update(orderItem); 33 | } 34 | 35 | public async Task ShipAsync(OrderItem orderItem) 36 | { 37 | return await base.UpdateAsync(orderItem); 38 | } 39 | 40 | public OrderItem Submit(OrderItem orderItem) 41 | { 42 | return base.Update(orderItem); 43 | } 44 | 45 | public async Task SubmitAsync(OrderItem orderItem) 46 | { 47 | return await base.UpdateAsync(orderItem); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/OrderStatusRepository.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | 4 | namespace Orders.com.DAL.EF 5 | { 6 | public class OrderStatusRepository : OrdersDotComRepositoryBase, IOrderStatusDataProxy 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/OrdersDotComContext.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using System.Data.Entity; 3 | 4 | namespace Orders.com.DAL.EF 5 | { 6 | public class OrdersDotComContext : DbContext 7 | { 8 | public DbSet Categories { get; set; } 9 | public DbSet Customers { get; set; } 10 | public DbSet InventoryItems { get; set; } 11 | public DbSet Orders { get; set; } 12 | public DbSet OrderItems { get; set; } 13 | public DbSet OrderStatuses { get; set; } 14 | public DbSet Products { get; set; } 15 | 16 | protected override void OnModelCreating(DbModelBuilder modelBuilder) 17 | { 18 | modelBuilder.Entity().Ignore(c => c.CategoryID); 19 | modelBuilder.Entity().Ignore(c => c.Self); 20 | 21 | modelBuilder.Entity().Ignore(c => c.CustomerID); 22 | modelBuilder.Entity().Ignore(c => c.Self); 23 | 24 | modelBuilder.Entity().Ignore(c => c.InventoryItemID); 25 | modelBuilder.Entity().Ignore(c => c.Self); 26 | 27 | modelBuilder.Entity().Ignore(c => c.OrderID); 28 | modelBuilder.Entity().Ignore(c => c.Self); 29 | 30 | modelBuilder.Entity().Ignore(c => c.OrderItemID); 31 | modelBuilder.Entity().Ignore(c => c.Self); 32 | 33 | modelBuilder.Entity().Ignore(c => c.OrderStatusID); 34 | modelBuilder.Entity().Ignore(c => c.Self); 35 | 36 | modelBuilder.Entity().Ignore(c => c.ProductID); 37 | modelBuilder.Entity().Ignore(c => c.Self); 38 | 39 | base.OnModelCreating(modelBuilder); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/OrdersDotComRepositoryBase.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Peasy; 3 | using Peasy.DataProxy.EF6; 4 | using System; 5 | using System.Data.Entity; 6 | using System.Threading.Tasks; 7 | 8 | namespace Orders.com.DAL.EF 9 | { 10 | public abstract class OrdersDotComRepositoryBase : EF6DataProxyBase, IServiceDataProxy where T : DomainBase, new() 11 | { 12 | public OrdersDotComRepositoryBase() : base(new MapsterHelper()) 13 | { 14 | } 15 | 16 | protected override DbContext GetDbContext() 17 | { 18 | return new OrdersDotComContext(); 19 | } 20 | 21 | public override T Insert(T entity) 22 | { 23 | entity.CreatedDatetime = DateTime.Now; 24 | return base.Insert(entity); 25 | } 26 | 27 | public override Task InsertAsync(T entity) 28 | { 29 | entity.CreatedDatetime = DateTime.Now; 30 | return base.InsertAsync(entity); 31 | } 32 | 33 | public override T Update(T entity) 34 | { 35 | entity.LastModifiedDatetime = DateTime.Now; 36 | return base.Update(entity); 37 | } 38 | 39 | public override Task UpdateAsync(T entity) 40 | { 41 | entity.LastModifiedDatetime = DateTime.Now; 42 | return base.UpdateAsync(entity); 43 | } 44 | 45 | public bool SupportsTransactions 46 | { 47 | get { return true; } 48 | } 49 | 50 | public bool IsLatencyProne 51 | { 52 | get { return false; } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/ProductRepository.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | using System.Collections.Generic; 4 | using System.Data.Entity; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Orders.com.DAL.EF 9 | { 10 | public class ProductRepository : OrdersDotComRepositoryBase, IProductDataProxy 11 | { 12 | public IEnumerable GetByCategory(long categoryID) 13 | { 14 | using (var context = GetDbContext()) 15 | { 16 | return context.Set().Where(i => i.CategoryID == categoryID).ToList(); 17 | } 18 | } 19 | 20 | public async Task> GetByCategoryAsync(long categoryID) 21 | { 22 | using (var context = GetDbContext()) 23 | { 24 | return await context.Set().Where(i => i.CategoryID == categoryID).ToListAsync(); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/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("Orders.com.DAL.EF")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Orders.com.DAL.EF")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 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("5c72c89f-28a0-4852-a5a4-a2eef6021a9f")] 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 | -------------------------------------------------------------------------------- /Orders.com.DAL.EF/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/CategoriesHttpServiceProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | 4 | namespace Orders.com.DAL.Http 5 | { 6 | public class CategoriesHttpServiceProxy : OrdersDotComHttpProxyBase, ICategoryDataProxy 7 | { 8 | public CategoriesHttpServiceProxy(string baseAddress) :base(baseAddress) { } 9 | 10 | protected override string RequestUri 11 | { 12 | get { return $"{BaseAddress}/categories"; } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/CustomersHttpServiceProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | 4 | namespace Orders.com.DAL.Http 5 | { 6 | public class CustomersHttpServiceProxy : OrdersDotComHttpProxyBase, ICustomerDataProxy 7 | { 8 | public CustomersHttpServiceProxy(string baseAddress) :base(baseAddress) { } 9 | 10 | protected override string RequestUri 11 | { 12 | get { return $"{BaseAddress}/customers"; } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/HttpClientExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using System.Net.Http.Headers; 3 | 4 | namespace Orders.com.DAL.Http 5 | { 6 | public static class HttpClientExtensions 7 | { 8 | public static HttpClient WithAcceptHeader(this HttpClient client, string mimeType) 9 | { 10 | client.DefaultRequestHeaders.Accept.Clear(); 11 | client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(mimeType)); 12 | return client; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/InventoryItemsHttpServiceProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | using System.Threading.Tasks; 4 | 5 | namespace Orders.com.DAL.Http 6 | { 7 | public class InventoryItemsHttpServiceProxy : OrdersDotComHttpProxyBase, IInventoryItemDataProxy 8 | { 9 | public InventoryItemsHttpServiceProxy(string baseAddress) :base(baseAddress) { } 10 | 11 | protected override string RequestUri 12 | { 13 | get { return $"{BaseAddress}/inventoryitems"; } 14 | } 15 | 16 | public InventoryItem GetByProduct(long productID) 17 | { 18 | return base.GET($"{RequestUri}?productid={productID}"); 19 | } 20 | 21 | public Task GetByProductAsync(long productID) 22 | { 23 | return base.GETAsync($"{RequestUri}?productid={productID}"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/OrderItemsHttpServiceProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Orders.com.DAL.Http 7 | { 8 | public class OrderItemsHttpServiceProxy : OrdersDotComHttpProxyBase, IOrderItemDataProxy 9 | { 10 | public OrderItemsHttpServiceProxy(string baseAddress) :base(baseAddress) { } 11 | 12 | protected override string RequestUri 13 | { 14 | get { return $"{BaseAddress}/orderitems"; } 15 | } 16 | 17 | public IEnumerable GetByOrder(long orderID) 18 | { 19 | return base.GET>($"{RequestUri}?orderid={orderID}"); 20 | } 21 | 22 | public Task> GetByOrderAsync(long orderID) 23 | { 24 | return base.GETAsync>($"{RequestUri}?orderid={orderID}"); 25 | } 26 | 27 | public OrderItem Ship(OrderItem orderItem) 28 | { 29 | return base.PUT(orderItem, $"{RequestUri}/{orderItem.ID}/ship"); 30 | } 31 | 32 | public Task ShipAsync(OrderItem orderItem) 33 | { 34 | return base.PUTAsync(orderItem, $"{RequestUri}/{orderItem.ID}/ship"); 35 | } 36 | 37 | public OrderItem Submit(OrderItem orderItem) 38 | { 39 | return base.PUT(orderItem, $"{RequestUri}/{orderItem.ID}/submit"); 40 | } 41 | 42 | public Task SubmitAsync(OrderItem orderItem) 43 | { 44 | return base.PUTAsync(orderItem, $"{RequestUri}/{orderItem.ID}/submit"); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/OrdersDotComHttpProxyBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using Peasy.DataProxy.Http; 4 | using Peasy; 5 | 6 | namespace Orders.com.DAL.Http 7 | { 8 | public abstract class OrdersDotComHttpProxyBase : HttpServiceProxyBase where T : IDomainObject 9 | { 10 | public OrdersDotComHttpProxyBase(string baseAddress) 11 | { 12 | BaseAddress = baseAddress; 13 | } 14 | 15 | protected virtual string BaseAddress 16 | { 17 | get;set; 18 | //get 19 | //{ 20 | // string hostSettingName = "apiHostNameAddress"; 21 | // var baseAddress = System.Configuration.ConfigurationManager.AppSettings[hostSettingName]; 22 | // if (baseAddress == null) throw new Exception($"The setting '{hostSettingName}' in the AppSettings portion of the configuration file was not found."); 23 | // return baseAddress; 24 | //} 25 | } 26 | 27 | protected override string OnFormatServerError(string message) 28 | { 29 | var msg = message.Split(new[] { ':' })[1]; 30 | Regex rgx = new Regex("[\\{\\}\"]"); // get rid of the quotes and braces 31 | msg = rgx.Replace(msg, "").Trim(); 32 | return msg; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/OrdersHttpServiceProxy.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Orders.com.BLL.Domain; 4 | using Orders.com.BLL.DataProxy; 5 | using Orders.com.BLL.QueryData; 6 | 7 | namespace Orders.com.DAL.Http 8 | { 9 | public class OrdersHttpServiceProxy : OrdersDotComHttpProxyBase, IOrderDataProxy 10 | { 11 | public OrdersHttpServiceProxy(string baseAddress) :base(baseAddress) { } 12 | 13 | protected override string RequestUri 14 | { 15 | get { return $"{BaseAddress}/orders"; } 16 | } 17 | 18 | public IEnumerable GetAll(int start, int pageSize) 19 | { 20 | return base.GET>($"{RequestUri}?start={start}&pagesize={pageSize}"); 21 | } 22 | 23 | public Task> GetAllAsync(int start, int pageSize) 24 | { 25 | return base.GETAsync>($"{RequestUri}?start={start}&pagesize={pageSize}"); 26 | } 27 | 28 | public IEnumerable GetByCustomer(long customerID) 29 | { 30 | return base.GET>($"{RequestUri}?customerid={customerID}"); 31 | } 32 | 33 | public Task> GetByCustomerAsync(long customerID) 34 | { 35 | return base.GETAsync>($"{RequestUri}?customerid={customerID}"); 36 | } 37 | 38 | public IEnumerable GetByProduct(long productID) 39 | { 40 | return base.GET>($"{RequestUri}?productid={productID}"); 41 | } 42 | 43 | public Task> GetByProductAsync(long productID) 44 | { 45 | return base.GETAsync>($"{RequestUri}?productid={productID}"); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/ProductsHttpServiceProxy.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Orders.com.DAL.Http 7 | { 8 | public class ProductsHttpServiceProxy : OrdersDotComHttpProxyBase, IProductDataProxy 9 | { 10 | public ProductsHttpServiceProxy(string baseAddress) :base(baseAddress) { } 11 | 12 | protected override string RequestUri 13 | { 14 | get { return $"{BaseAddress}/products"; } 15 | } 16 | 17 | public IEnumerable GetByCategory(long categoryID) 18 | { 19 | return base.GET>($"{RequestUri}?categoryid={categoryID}"); 20 | } 21 | 22 | public Task> GetByCategoryAsync(long categoryID) 23 | { 24 | return base.GETAsync>($"{RequestUri}?categoryid={categoryID}"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Resources; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Orders.com.DAL.Http")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Orders.com.DAL.Http")] 14 | [assembly: AssemblyCopyright("Copyright © 2017")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: NeutralResourcesLanguage("en")] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | -------------------------------------------------------------------------------- /Orders.com.DAL.Http/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "supports": {}, 3 | "dependencies": { 4 | "Microsoft.NETCore.Portable.Compatibility": "1.0.1", 5 | "NETStandard.Library": "1.6.0", 6 | "Peasy.DataProxy.Http": "2.0.0" 7 | }, 8 | "frameworks": { 9 | "netstandard1.1": {} 10 | } 11 | } -------------------------------------------------------------------------------- /Orders.com.DAL.InMemory/CategoryRepository.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | using System.Collections.Generic; 4 | 5 | namespace Orders.com.DAL.InMemory 6 | { 7 | public class CategoryRepository : OrdersDotComRepositoryBase, ICategoryDataProxy 8 | { 9 | protected override IEnumerable SeedDataProxy() 10 | { 11 | yield return new Category() { CategoryID = 1, Name = "Guitars" }; 12 | yield return new Category() { CategoryID = 2, Name = "Computers" }; 13 | yield return new Category() { CategoryID = 3, Name = "Albums" }; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Orders.com.DAL.InMemory/CustomerRepository.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | using System.Collections.Generic; 4 | 5 | namespace Orders.com.DAL.InMemory 6 | { 7 | public class CustomerRepository : OrdersDotComRepositoryBase, ICustomerDataProxy 8 | { 9 | protected override IEnumerable SeedDataProxy() 10 | { 11 | yield return new Customer() { CustomerID = 1, Name = "Jimi Hendrix" }; 12 | yield return new Customer() { CustomerID = 2, Name = "David Gilmour" }; 13 | yield return new Customer() { CustomerID = 3, Name = "James Page" }; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Orders.com.DAL.InMemory/InventoryItemRepository.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Orders.com.BLL.DataProxy; 3 | using Orders.com.BLL.Domain; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace Orders.com.DAL.InMemory 10 | { 11 | public class InventoryItemRepository : OrdersDotComRepositoryBase, IInventoryItemDataProxy 12 | { 13 | protected override IEnumerable SeedDataProxy() 14 | { 15 | yield return new InventoryItem() { InventoryItemID = 1, ProductID = 1, QuantityOnHand = 50, Version = "1" }; 16 | yield return new InventoryItem() { InventoryItemID = 2, ProductID = 2, QuantityOnHand = 1, Version = "1" }; 17 | yield return new InventoryItem() { InventoryItemID = 3, ProductID = 3, QuantityOnHand = 4, Version = "1" }; 18 | yield return new InventoryItem() { InventoryItemID = 4, ProductID = 4, QuantityOnHand = 3, Version = "1" }; 19 | yield return new InventoryItem() { InventoryItemID = 5, ProductID = 5, QuantityOnHand = 20, Version = "1" }; 20 | yield return new InventoryItem() { InventoryItemID = 6, ProductID = 6, QuantityOnHand = 54, Version = "1" }; 21 | yield return new InventoryItem() { InventoryItemID = 7, ProductID = 7, QuantityOnHand = 12, Version = "1" }; 22 | yield return new InventoryItem() { InventoryItemID = 8, ProductID = 8, QuantityOnHand = 10, Version = "1" }; 23 | yield return new InventoryItem() { InventoryItemID = 9, ProductID = 9, QuantityOnHand = 34, Version = "1" }; 24 | yield return new InventoryItem() { InventoryItemID = 10, ProductID = 10, QuantityOnHand = 11, Version = "1" }; 25 | } 26 | 27 | public InventoryItem GetByProduct(long productID) 28 | { 29 | Debug.WriteLine("Executing EF InventoryItem.GetByProduct"); 30 | var inventoryItem = Data.Values.First(c => c.ProductID == productID); 31 | return Mapper.Map(inventoryItem, new InventoryItem()); 32 | } 33 | 34 | public async Task GetByProductAsync(long productID) 35 | { 36 | return GetByProduct(productID); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Orders.com.DAL.InMemory/OrderItemRepository.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Orders.com.BLL.Domain; 7 | using Orders.com.BLL.DataProxy; 8 | 9 | namespace Orders.com.DAL.InMemory 10 | { 11 | public class OrderItemRepository : OrdersDotComRepositoryBase, IOrderItemDataProxy 12 | { 13 | public IEnumerable GetByOrder(long orderID) 14 | { 15 | Debug.WriteLine("Executing EF OrderItem.GetByOrder"); 16 | return Data.Values.Where(i => i.OrderID == orderID) 17 | .Select(Mapper.Map) 18 | .ToArray(); 19 | } 20 | 21 | public async Task> GetByOrderAsync(long orderID) 22 | { 23 | return GetByOrder(orderID); 24 | } 25 | 26 | public OrderItem Ship(OrderItem orderItem) 27 | { 28 | return Update(orderItem); 29 | } 30 | 31 | public Task ShipAsync(OrderItem orderItem) 32 | { 33 | return UpdateAsync(orderItem); 34 | } 35 | 36 | public OrderItem Submit(OrderItem orderItem) 37 | { 38 | return Update(orderItem); 39 | } 40 | 41 | public Task SubmitAsync(OrderItem orderItem) 42 | { 43 | return UpdateAsync(orderItem); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Orders.com.DAL.InMemory/OrderStatusRepository.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.DataProxy; 2 | using Orders.com.BLL.Domain; 3 | using System.Collections.Generic; 4 | 5 | namespace Orders.com.DAL.InMemory 6 | { 7 | public class OrderStatusRepository : OrdersDotComRepositoryBase, IOrderStatusDataProxy 8 | { 9 | protected override IEnumerable SeedDataProxy() 10 | { 11 | yield return new OrderStatus() { OrderStatusID = 1, Name = "Pending" }; 12 | yield return new OrderStatus() { OrderStatusID = 2, Name = "Submitted" }; 13 | yield return new OrderStatus() { OrderStatusID = 3, Name = "Shipped" }; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Orders.com.DAL.InMemory/OrdersDotComRepositoryBase.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Peasy; 3 | using Peasy.DataProxy.InMemory; 4 | using System.Collections.Generic; 5 | using Peasy.Exception; 6 | using Orders.com.BLL.Extensions; 7 | 8 | namespace Orders.com.DAL.InMemory 9 | { 10 | public class OrdersDotComRepositoryBase : InMemoryDataProxyBase where DTO : IDomainObject 11 | { 12 | public override DTO GetByID(long id) 13 | { 14 | try 15 | { 16 | return base.GetByID(id); 17 | } 18 | catch (KeyNotFoundException ex) 19 | { 20 | throw new DomainObjectNotFoundException("The current item was not found", ex); 21 | } 22 | } 23 | 24 | protected override long GetNextID() 25 | { 26 | if (Data.Values.Any()) 27 | return Data.Values.Max(c => c.ID) + 1; 28 | 29 | return 1; 30 | } 31 | 32 | public override IVersionContainer IncrementVersion(IVersionContainer versionContainer) 33 | { 34 | versionContainer.IncrementVersionByOne(); 35 | return versionContainer; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Orders.com.DAL.InMemory/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Resources; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Orders.com.DAL.InMemory")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Orders.com.DAL.InMemory")] 14 | [assembly: AssemblyCopyright("Copyright © 2017")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: NeutralResourcesLanguage("en")] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | -------------------------------------------------------------------------------- /Orders.com.DAL.InMemory/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "supports": {}, 3 | "dependencies": { 4 | "Microsoft.NETCore.Portable.Compatibility": "1.0.1", 5 | "NETStandard.Library": "1.6.0", 6 | "Peasy.DataProxy.InMemory": "2.0.0" 7 | }, 8 | "frameworks": { 9 | "netstandard1.1": {} 10 | } 11 | } -------------------------------------------------------------------------------- /Orders.com.WPF/App.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 | -------------------------------------------------------------------------------- /Orders.com.WPF/App.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Orders.com.WPF/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace Orders.com.WPF 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | public App() : base() 17 | { 18 | this.Dispatcher.UnhandledException += Dispatcher_UnhandledException; 19 | } 20 | 21 | void Dispatcher_UnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) 22 | { 23 | var message = e.Exception.Message; 24 | if (e.Exception is InvalidOperationException && e.Exception.Message == "Sequence contains no matching element") 25 | message = "This item no longer exists. Try refreshing your list"; 26 | 27 | MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); 28 | e.Handled = true; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Orders.com.WPF/Command.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Input; 3 | 4 | namespace Orders.com.WPF 5 | { 6 | public class Command : ICommand 7 | { 8 | private Action _action; 9 | private Func _canExecute; 10 | 11 | public Command(Action action) 12 | { 13 | _action = action; 14 | } 15 | 16 | public Command(Action action, Func canExecute) : this(action) 17 | { 18 | _canExecute = canExecute; 19 | } 20 | 21 | public bool CanExecute(object parameter) 22 | { 23 | if (_canExecute != null) 24 | return _canExecute(); 25 | 26 | return true; 27 | } 28 | 29 | public event EventHandler CanExecuteChanged 30 | { 31 | add { CommandManager.RequerySuggested += value; } 32 | remove { CommandManager.RequerySuggested -= value; } 33 | } 34 | 35 | public void Execute(object parameter) 36 | { 37 | _action(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Orders.com.WPF/Converters/DecimalConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Data; 7 | 8 | namespace Orders.com.WPF.Converters 9 | { 10 | public class DecimalConverter : IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 13 | { 14 | //var number = value.ToString() == "0" ? string.Empty : value; 15 | //return value.ToString(); 16 | return value; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 20 | { 21 | var number = string.IsNullOrWhiteSpace(value.ToString()) ? 0 : value; 22 | return Decimal.Parse(number.ToString()); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Orders.com.WPF/Converters/ErrorsConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace Orders.com.WPF.Converters 10 | { 11 | public class ErrorsConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 14 | { 15 | var errors = value as IEnumerable; 16 | var message = string.Join("\n", errors.Select(e => e.ErrorMessage).ToArray()); 17 | return message; 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Orders.com.WPF/Converters/VisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Data; 8 | 9 | namespace Orders.com.WPF.Converters 10 | { 11 | public class VisibilityConverter : IValueConverter 12 | { 13 | public bool Reverse { get; set; } 14 | 15 | public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 16 | { 17 | var val = (bool)value; 18 | if (Reverse) val = !val; 19 | if (val == false) 20 | return Visibility.Collapsed; 21 | 22 | return Visibility.Visible; 23 | } 24 | 25 | public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 26 | { 27 | throw new NotImplementedException(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Orders.com.WPF/CustomerOrderWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | using Orders.com.WPF.VM; 4 | using System.Windows; 5 | 6 | namespace Orders.com.WPF 7 | { 8 | /// 9 | /// Interaction logic for CustomerOrderWindow.xaml 10 | /// 11 | public partial class CustomerOrderWindow 12 | { 13 | public CustomerOrderWindow() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | public CustomerOrderWindow(OrderService orderService, 19 | CustomerService customerService, 20 | OrderItemService orderItemService, 21 | InventoryItemService inventoryService, 22 | MainWindowVM mainVM, 23 | EventAggregator eventAggregator) 24 | : this() 25 | { 26 | var vm = new CustomerOrderVM(eventAggregator, orderService, orderItemService, inventoryService, mainVM); 27 | DataContext = vm; 28 | } 29 | 30 | public CustomerOrderWindow(OrderVM currentOrder, 31 | OrderService orderService, 32 | CustomerService customerService, 33 | OrderItemService orderItemService, 34 | InventoryItemService inventoryService, 35 | MainWindowVM mainVM, 36 | EventAggregator eventAggregator) 37 | : this() 38 | { 39 | var order = new Order() 40 | { 41 | ID = currentOrder.ID, 42 | CustomerID = currentOrder.CustomerID, 43 | OrderDate = currentOrder.OrderDate, 44 | }; 45 | var vm = new CustomerOrderVM(eventAggregator, order, orderService, orderItemService, inventoryService, mainVM); 46 | vm.RefreshCommand.Execute(null); 47 | DataContext = vm; 48 | } 49 | 50 | private void CloseWindowClick(object sender, RoutedEventArgs e) 51 | { 52 | this.Close(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Orders.com.WPF/DTCTransactionContext.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using System; 3 | using System.Threading.Tasks; 4 | using System.Transactions; 5 | 6 | namespace Orders.com.WPF 7 | { 8 | public class DTCTransactionContext : ITransactionContext 9 | { 10 | public void Execute(Action codeToRunWithinTransaction) 11 | { 12 | using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, new System.TimeSpan(0, 5, 0))) 13 | { 14 | codeToRunWithinTransaction(); 15 | transactionScope.Complete(); 16 | } 17 | } 18 | 19 | public T Execute(Func codeToRunWithinTransaction) 20 | { 21 | using (var transactionScope = new TransactionScope()) 22 | { 23 | var result = codeToRunWithinTransaction(); 24 | transactionScope.Complete(); 25 | return result; 26 | } 27 | } 28 | 29 | public async Task ExecuteAsync(Func> codeToRunWithinTransaction) 30 | { 31 | using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 32 | { 33 | var result = await codeToRunWithinTransaction(); 34 | transactionScope.Complete(); 35 | return result; 36 | } 37 | } 38 | 39 | public async Task ExecuteAsync(Func codeToRunWithinTransaction) 40 | { 41 | using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 42 | { 43 | await codeToRunWithinTransaction(); 44 | transactionScope.Complete(); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Orders.com.WPF/Images/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.WPF/Images/add.png -------------------------------------------------------------------------------- /Orders.com.WPF/Images/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.WPF/Images/cancel.png -------------------------------------------------------------------------------- /Orders.com.WPF/Images/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.WPF/Images/delete.png -------------------------------------------------------------------------------- /Orders.com.WPF/Images/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.WPF/Images/edit.png -------------------------------------------------------------------------------- /Orders.com.WPF/Images/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.WPF/Images/next.png -------------------------------------------------------------------------------- /Orders.com.WPF/Images/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.WPF/Images/save.png -------------------------------------------------------------------------------- /Orders.com.WPF/Images/sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.WPF/Images/sync.png -------------------------------------------------------------------------------- /Orders.com.WPF/Images/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.WPF/Images/warning.png -------------------------------------------------------------------------------- /Orders.com.WPF/OrderInsertedEvent.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.WPF.VM; 2 | 3 | namespace Orders.com.WPF 4 | { 5 | public class OrderInsertedEvent 6 | { 7 | public CustomerOrderVM Order { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Orders.com.WPF/OrderUpdatedEvent.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.WPF.VM; 2 | 3 | namespace Orders.com.WPF 4 | { 5 | public class OrderUpdatedEvent 6 | { 7 | public OrderUpdatedEvent(CustomerOrderVM order) 8 | { 9 | Order = order; 10 | } 11 | 12 | public CustomerOrderVM Order { get; private set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Orders.com.WPF/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Orders.com.WPF.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Orders.com.WPF/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Orders.com.WPF/VM/CategoryVM.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | 4 | namespace Orders.com.WPF.VM 5 | { 6 | public class CategoryVM : OrdersDotComVMBase 7 | { 8 | public CategoryVM (CategoryService service) : base(service) 9 | { 10 | } 11 | 12 | public CategoryVM(Category customer, CategoryService service) : base(customer, service) 13 | { 14 | } 15 | 16 | public long ID 17 | { 18 | get { return CurrentEntity.ID; } 19 | } 20 | 21 | public string Name 22 | { 23 | get { return CurrentEntity.Name; } 24 | set 25 | { 26 | CurrentEntity.Name = value; 27 | IsDirty = true; 28 | OnPropertyChanged("Name"); 29 | } 30 | } 31 | 32 | protected override void OnInsertSuccess(Category result) 33 | { 34 | OnPropertyChanged("ID"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Orders.com.WPF/VM/CustomerVM.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | 4 | namespace Orders.com.WPF.VM 5 | { 6 | public class CustomerVM : OrdersDotComVMBase 7 | { 8 | public CustomerVM (CustomerService service) : base(service) 9 | { 10 | } 11 | 12 | public CustomerVM(Customer customer, CustomerService service) : base(customer, service) 13 | { 14 | } 15 | 16 | public long ID 17 | { 18 | get { return CurrentEntity.ID; } 19 | } 20 | 21 | public string Name 22 | { 23 | get { return CurrentEntity.Name; } 24 | set 25 | { 26 | CurrentEntity.Name = value; 27 | IsDirty = true; 28 | OnPropertyChanged("Name"); 29 | } 30 | } 31 | 32 | protected override void OnInsertSuccess(Customer result) 33 | { 34 | OnPropertyChanged("ID"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Orders.com.WPF/VM/InventoryItemVM.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Orders.com.BLL.Services; 3 | using Orders.com.BLL.Domain; 4 | 5 | namespace Orders.com.WPF.VM 6 | { 7 | public class InventoryItemVM : OrdersDotComVMBase 8 | { 9 | private MainWindowVM _mainVM; 10 | 11 | public InventoryItemVM (InventoryItemService service) : base(service) 12 | { 13 | } 14 | 15 | public InventoryItemVM(InventoryItem item, InventoryItemService service, MainWindowVM mainVM) : base(item, service) 16 | { 17 | _mainVM = mainVM; 18 | } 19 | 20 | public string Name 21 | { 22 | get 23 | { 24 | return _mainVM.ProductsVM.Products.First(p => p.ID == CurrentEntity.ProductID).Name; 25 | } 26 | } 27 | 28 | public decimal QuantityOnHand 29 | { 30 | get { return CurrentEntity.QuantityOnHand; } 31 | set 32 | { 33 | CurrentEntity.QuantityOnHand = value; 34 | IsDirty = true; 35 | OnPropertyChanged("QuantityOnHand"); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Orders.com.WPF/VM/MainWindowVM.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Services; 2 | 3 | namespace Orders.com.WPF.VM 4 | { 5 | public class MainWindowVM : ViewModelBase 6 | { 7 | private CustomersVM _customersVM; 8 | private ProductsVM _productsVM; 9 | private CategoriesVM _categoriesVM; 10 | private OrdersVM _ordersVM; 11 | private InventoryItemsVM _inventoryItemsVM; 12 | 13 | public MainWindowVM(EventAggregator eventAggregator, 14 | CustomerService customerService, 15 | ProductService productService, 16 | CategoryService categoryService, 17 | OrderService orderService, 18 | InventoryItemService inventoryService) 19 | { 20 | _customersVM = new CustomersVM(customerService); 21 | _customersVM.LoadCustomersCommand.Execute(null); 22 | _productsVM = new ProductsVM(productService, this); 23 | _productsVM.LoadProductsCommand.Execute(null); 24 | _categoriesVM = new CategoriesVM(categoryService); 25 | _categoriesVM.LoadCategoriesCommand.Execute(null); 26 | _ordersVM = new OrdersVM(orderService, this, eventAggregator); 27 | _ordersVM.LoadOrdersCommand.Execute(null); 28 | _inventoryItemsVM = new InventoryItemsVM(inventoryService, this); 29 | _inventoryItemsVM.LoadInventoryCommand.Execute(null); 30 | } 31 | 32 | public CustomersVM CustomersVM 33 | { 34 | get { return _customersVM; } 35 | } 36 | 37 | public ProductsVM ProductsVM 38 | { 39 | get { return _productsVM; } 40 | } 41 | 42 | public CategoriesVM CategoriesVM 43 | { 44 | get { return _categoriesVM; } 45 | } 46 | 47 | public OrdersVM OrdersVM 48 | { 49 | get { return _ordersVM; } 50 | } 51 | 52 | public InventoryItemsVM InventoryItemsVM 53 | { 54 | get { return _inventoryItemsVM; } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Orders.com.WPF/VM/OrdersDotComVMBase.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL; 2 | using Orders.com; 3 | using Orders.com.BLL.Services; 4 | using Orders.com.BLL.Domain; 5 | 6 | namespace Orders.com.WPF.VM 7 | { 8 | public abstract class OrdersDotComVMBase : EntityViewModelBase where T : DomainBase, new() 9 | { 10 | public OrdersDotComVMBase(OrdersDotComServiceBase service) : base(service) 11 | { 12 | } 13 | 14 | public OrdersDotComVMBase(T entity, OrdersDotComServiceBase service) : base(entity, service) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Orders.com.WPF/VM/ProductVM.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | using System.Collections.Generic; 4 | 5 | namespace Orders.com.WPF.VM 6 | { 7 | public class ProductVM : OrdersDotComVMBase 8 | { 9 | private MainWindowVM _mainVM; 10 | 11 | public ProductVM(ProductService service, MainWindowVM mainVM) : base(service) 12 | { 13 | _mainVM = mainVM; 14 | } 15 | 16 | public ProductVM(Product product, ProductService service, MainWindowVM mainVM) : base(product, service) 17 | { 18 | _mainVM = mainVM; 19 | } 20 | 21 | public IEnumerable Categories 22 | { 23 | get { return _mainVM.CategoriesVM.Categories; } 24 | } 25 | 26 | public long ID 27 | { 28 | get { return CurrentEntity.ID; } 29 | } 30 | 31 | public string Name 32 | { 33 | get { return CurrentEntity.Name; } 34 | set 35 | { 36 | CurrentEntity.Name = value; 37 | IsDirty = true; 38 | OnPropertyChanged("Name"); 39 | } 40 | } 41 | 42 | public decimal? Price 43 | { 44 | get { return CurrentEntity.Price; } 45 | set 46 | { 47 | CurrentEntity.Price = value; 48 | IsDirty = true; 49 | OnPropertyChanged("Price"); 50 | } 51 | } 52 | 53 | public string Description 54 | { 55 | get { return CurrentEntity.Description; } 56 | set 57 | { 58 | CurrentEntity.Description = value; 59 | IsDirty = true; 60 | OnPropertyChanged("Description"); 61 | } 62 | } 63 | 64 | public long CurrentCategoryID 65 | { 66 | get { return CurrentEntity.CategoryID; } 67 | set 68 | { 69 | CurrentEntity.CategoryID = value; 70 | IsDirty = true; 71 | OnPropertyChanged("CurrentCategoryID"); 72 | } 73 | } 74 | 75 | protected override void OnInsertSuccess(Product result) 76 | { 77 | OnPropertyChanged("ID"); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace Orders.com.Web.Api 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/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 Orders.com.Web.Api 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 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.Web.Api.Filters; 2 | using System.Web.Http; 3 | 4 | namespace Orders.com.Web.Api 5 | { 6 | public static class WebApiConfig 7 | { 8 | public static void Register(HttpConfiguration config) 9 | { 10 | // Web API configuration and services 11 | GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(NinjectWebCommon.CreateKernel()); 12 | 13 | // Web API routes 14 | config.MapHttpAttributeRoutes(); 15 | 16 | config.Routes.MapHttpRoute( 17 | name: "children", 18 | routeTemplate: "api/{controller}/{id}/{action}", 19 | defaults: new { id = RouteParameter.Optional } 20 | ); 21 | 22 | config.Routes.MapHttpRoute( 23 | name: "DefaultApi", 24 | routeTemplate: "api/{controller}/{id}", 25 | defaults: new { id = RouteParameter.Optional } 26 | ); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Configuration/DIConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace Orders.com.Web.Api.Configuration 4 | { 5 | public class DIConfig : ConfigurationSection 6 | { 7 | [ConfigurationProperty("fromType", IsKey=true)] 8 | public string FromType 9 | { 10 | get { return (string)base["fromType"]; } 11 | set { base["fromType"] = value; } 12 | } 13 | 14 | [ConfigurationProperty("toType")] 15 | public string ToType 16 | { 17 | get { return (string)base["toType"]; } 18 | set { base["toType"] = value; } 19 | } 20 | 21 | [ConfigurationProperty("defaultProperties")] 22 | public DIDefaultPropConfigList DefaultProperties 23 | { 24 | get { return (DIDefaultPropConfigList)base["defaultProperties"]; } 25 | set { base["defaultProperties"] = value; } 26 | } 27 | 28 | [ConfigurationProperty("asSingleton")] 29 | public bool AsSingleton 30 | { 31 | get { return (bool)base["asSingleton"]; } 32 | set { base["asSingleton"] = value; } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Configuration/DIConfigList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Configuration; 3 | 4 | namespace Orders.com.Web.Api.Configuration 5 | { 6 | public class DIConfigList : ConfigurationElementCollection, IEnumerable 7 | { 8 | #region ConfigurationElementCollection 9 | protected override ConfigurationElement CreateNewElement() 10 | { 11 | return new DIConfig(); 12 | } 13 | 14 | protected override object GetElementKey(ConfigurationElement element) 15 | { 16 | return ((DIConfig)element).FromType; 17 | } 18 | #endregion 19 | 20 | #region IEnumerable 21 | public new IEnumerator GetEnumerator() 22 | { 23 | return GetAll().GetEnumerator(); 24 | } 25 | #endregion 26 | 27 | public DIConfig this[int index] 28 | { 29 | get { return (DIConfig)BaseGet(index); } 30 | } 31 | 32 | new public DIConfig this[string name] 33 | { 34 | get { return (DIConfig)BaseGet(name); } 35 | } 36 | 37 | public void Add(DIConfig entry) 38 | { 39 | this.BaseAdd(entry); 40 | } 41 | 42 | public IEnumerable GetAll() 43 | { 44 | for (int i = 0; i < this.Count; i++) 45 | yield return this[i]; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Configuration/DIConfigSection.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace Orders.com.Web.Api.Configuration 4 | { 5 | public class DIConfigSection : ConfigurationSection 6 | { 7 | [ConfigurationProperty("bindings")] 8 | public DIConfigList Bindings 9 | { 10 | get { return (DIConfigList)base["bindings"]; } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Configuration/DIDefaultPropConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace Orders.com.Web.Api.Configuration 4 | { 5 | public class DIDefaultPropConfig : ConfigurationElement 6 | { 7 | [ConfigurationProperty("propertyName")] 8 | public string PropertyName 9 | { 10 | get { return (string)base["propertyName"]; } 11 | set { base["propertyName"] = value; } 12 | } 13 | 14 | [ConfigurationProperty("value")] 15 | public string Value 16 | { 17 | get { return (string)base["value"]; } 18 | set { base["value"] = value; } 19 | } 20 | 21 | [ConfigurationProperty("type")] 22 | public string Type 23 | { 24 | get { return (string)base["type"]; } 25 | set { base["type"] = value; } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | 6 | namespace Orders.com.Web.Api 7 | { 8 | public class Constants 9 | { 10 | public const string ROUTE_NAME_DEFAULT = "DefaultApi"; 11 | } 12 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/Controllers/CategoriesController.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | 4 | namespace Orders.com.Web.Api.Controllers 5 | { 6 | public class CategoriesController : ApiControllerBase 7 | { 8 | public CategoriesController(ICategoryService categoryService) 9 | { 10 | _businessService = categoryService; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/Controllers/CustomersController.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | 4 | namespace Orders.com.Web.Api.Controllers 5 | { 6 | public class CustomersController : ApiControllerBase 7 | { 8 | public CustomersController(ICustomerService customerService) 9 | { 10 | _businessService = customerService; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/Controllers/InventoryItemsController.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | using System.Web.Http; 4 | 5 | namespace Orders.com.Web.Api.Controllers 6 | { 7 | public class InventoryItemsController : ApiControllerBase 8 | { 9 | public InventoryItemsController(IInventoryItemService inventoryService) 10 | { 11 | _businessService = inventoryService; 12 | } 13 | 14 | [HttpGet] 15 | /// GET api/inventoryitems?productid=123 16 | public InventoryItem GetByProduct(long productID) 17 | { 18 | var item = (_businessService as IInventoryItemService).GetByProductCommand(productID).Execute().Value; 19 | return item; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/Controllers/OrderItemsController.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Web.Http; 6 | 7 | namespace Orders.com.Web.Api.Controllers 8 | { 9 | public class OrderItemsController : ApiControllerBase 10 | { 11 | public OrderItemsController(IOrderItemService orderItemService) 12 | { 13 | _businessService = orderItemService; 14 | } 15 | 16 | private IOrderItemService BusinessService 17 | { 18 | get { return _businessService as IOrderItemService; } 19 | } 20 | 21 | [HttpGet] 22 | /// GET api/orderitems?orderid=123 23 | public IEnumerable GetByOrder(long orderID) 24 | { 25 | var orderItems = BusinessService.GetByOrderCommand(orderID).Execute().Value; 26 | return orderItems; 27 | } 28 | 29 | [HttpPut] 30 | /// PUT api/orderitems/123/submit 31 | [Route("api/orderitems/{orderitemid:long}/submit")] 32 | public IHttpActionResult Submit(long orderItemID) 33 | { 34 | var result = BusinessService.SubmitCommand(orderItemID).Execute(); 35 | if (result.Success) 36 | return Ok(result.Value); 37 | 38 | return BadRequest(string.Join(",", result.Errors.Select(e => e.ErrorMessage))); 39 | } 40 | 41 | [HttpPut] 42 | /// PUT api/orderitems/123/ship 43 | [Route("api/orderitems/{orderitemid:long}/ship")] 44 | public IHttpActionResult Ship(long orderItemID) 45 | { 46 | var result = BusinessService.ShipCommand(orderItemID).Execute(); 47 | if (result.Success) 48 | return Ok(result.Value); 49 | 50 | return BadRequest(string.Join(",", result.Errors.Select(e => e.ErrorMessage))); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/Controllers/OrdersController.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.QueryData; 3 | using Orders.com.BLL.Services; 4 | using System.Collections.Generic; 5 | using System.Web.Http; 6 | 7 | namespace Orders.com.Web.Api.Controllers 8 | { 9 | public class OrdersController : ApiControllerBase 10 | { 11 | public OrdersController(IOrderService orderService) 12 | { 13 | _businessService = orderService; 14 | } 15 | 16 | [HttpGet] 17 | /// GET api/orders?start=1&pagesize=10 18 | public IEnumerable GetAll(int start, int pageSize) 19 | { 20 | var orderInfos = (_businessService as IOrderService).GetAllCommand(start, pageSize).Execute().Value; 21 | return orderInfos; 22 | } 23 | 24 | [HttpGet] 25 | /// GET api/orders?customerid=123 26 | public IEnumerable GetByCustomer(long customerID) 27 | { 28 | var orders = (_businessService as IOrderService).GetByCustomerCommand(customerID).Execute().Value; 29 | return orders; 30 | } 31 | 32 | [HttpGet] 33 | /// GET api/orders?productid=123 34 | public IEnumerable GetByProduct(long productID) 35 | { 36 | var orders = (_businessService as IOrderService).GetByProductCommand(productID).Execute().Value; 37 | return orders; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Controllers/ProductsController.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | using System.Collections.Generic; 4 | using System.Web.Http; 5 | 6 | namespace Orders.com.Web.Api.Controllers 7 | { 8 | public class ProductsController : ApiControllerBase 9 | { 10 | public ProductsController(IProductService productService) 11 | { 12 | _businessService = productService; 13 | } 14 | 15 | [HttpGet] 16 | /// GET api/products?categoryid=123 17 | public IEnumerable GetByCategory(long categoryID) 18 | { 19 | var products = (_businessService as IProductService).GetByCategoryCommand(categoryID).Execute().Value; 20 | return products; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/DTCTransactionContext.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using System; 3 | using System.Threading.Tasks; 4 | using System.Transactions; 5 | 6 | namespace Orders.com.Web.Api 7 | { 8 | public class DTCTransactionContext : ITransactionContext 9 | { 10 | public void Execute(Action codeToRunWithinTransaction) 11 | { 12 | using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, new System.TimeSpan(0, 5, 0))) 13 | { 14 | codeToRunWithinTransaction(); 15 | transactionScope.Complete(); 16 | } 17 | } 18 | 19 | public T Execute(Func codeToRunWithinTransaction) 20 | { 21 | using (var transactionScope = new TransactionScope()) 22 | { 23 | var result = codeToRunWithinTransaction(); 24 | transactionScope.Complete(); 25 | return result; 26 | } 27 | } 28 | 29 | public async Task ExecuteAsync(Func> codeToRunWithinTransaction) 30 | { 31 | using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 32 | { 33 | var result = await codeToRunWithinTransaction(); 34 | transactionScope.Complete(); 35 | return result; 36 | } 37 | } 38 | 39 | public async Task ExecuteAsync(Func codeToRunWithinTransaction) 40 | { 41 | using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 42 | { 43 | await codeToRunWithinTransaction(); 44 | transactionScope.Complete(); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Extensions/IDomainObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Web; 7 | 8 | namespace Orders.com.Web.Api 9 | { 10 | public static class IDomainObjectExtensions 11 | { 12 | public static string ClassName(this T domainObject) where T : IDomainObject 13 | { 14 | var type = domainObject.GetType(); 15 | var displayAttribute = type.GetCustomAttributes(true) 16 | .FirstOrDefault(a => a is DisplayNameAttribute) as DisplayNameAttribute; 17 | 18 | if (displayAttribute != null) 19 | return displayAttribute.DisplayName; 20 | 21 | return type.Name; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/Extensions/ModelStateDictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.Linq; 4 | using System.Web.Http.ModelBinding; 5 | 6 | namespace Orders.com.Web.Api 7 | { 8 | public static class ModelStateDictionaryExtensions 9 | { 10 | public static ModelStateDictionary ClearFirst(this ModelStateDictionary modelState) 11 | { 12 | modelState.Clear(); 13 | return modelState; 14 | } 15 | 16 | public static ModelStateDictionary ThenAddRange(this ModelStateDictionary modelState, IEnumerable validationResults) 17 | { 18 | foreach (var error in validationResults) 19 | { 20 | if (error.MemberNames.Any()) 21 | modelState.AddModelError(error.MemberNames.First(), error.ErrorMessage); 22 | else 23 | modelState.AddModelError(string.Empty, error.ErrorMessage); 24 | } 25 | return modelState; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/Filters/NinjectScope.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http.Dependencies; 5 | using Ninject; 6 | using Ninject.Activation; 7 | using Ninject.Parameters; 8 | using Ninject.Syntax; 9 | 10 | namespace Orders.com.Web.Api.Filters 11 | { 12 | public class NinjectScope : IDependencyScope 13 | { 14 | protected IResolutionRoot resolutionRoot; 15 | 16 | public NinjectScope(IResolutionRoot kernel) 17 | { 18 | resolutionRoot = kernel; 19 | } 20 | 21 | public object GetService(Type serviceType) 22 | { 23 | IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true); 24 | return resolutionRoot.Resolve(request).SingleOrDefault(); 25 | } 26 | 27 | public IEnumerable GetServices(Type serviceType) 28 | { 29 | IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true); 30 | return resolutionRoot.Resolve(request).ToList(); 31 | } 32 | 33 | public void Dispose() 34 | { 35 | } 36 | } 37 | 38 | public class NinjectResolver : NinjectScope, IDependencyResolver 39 | { 40 | private IKernel _kernel; 41 | public NinjectResolver(IKernel kernel) 42 | : base(kernel) 43 | { 44 | _kernel = kernel; 45 | } 46 | 47 | public IDependencyScope BeginScope() 48 | { 49 | return new NinjectScope(_kernel); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Orders.com.Web.Api/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Orders.com.Web.Api.WebApiApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Mvc; 7 | using System.Web.Routing; 8 | 9 | namespace Orders.com.Web.Api 10 | { 11 | public class WebApiApplication : System.Web.HttpApplication 12 | { 13 | protected void Application_Start() 14 | { 15 | AreaRegistration.RegisterAllAreas(); 16 | GlobalConfiguration.Configure(WebApiConfig.Register); 17 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 18 | RouteConfig.RegisterRoutes(RouteTable.Routes); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/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("Orders.com.Web.Api")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Orders.com.Web.Api")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 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("8871008c-06a0-4a4d-b62b-968f51a2b996")] 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 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Orders.com.Web.Api/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.Web.Api/favicon.ico -------------------------------------------------------------------------------- /Orders.com.Web.Api/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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace Orders.com.Web.MVC 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit http://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 http://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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace Orders.com.Web.MVC 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 Orders.com.Web.MVC 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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Configuration/DIConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace Orders.com.Web.MVC.Configuration 4 | { 5 | public class DIConfig : ConfigurationSection 6 | { 7 | [ConfigurationProperty("fromType", IsKey=true)] 8 | public string FromType 9 | { 10 | get { return (string)base["fromType"]; } 11 | set { base["fromType"] = value; } 12 | } 13 | 14 | [ConfigurationProperty("toType")] 15 | public string ToType 16 | { 17 | get { return (string)base["toType"]; } 18 | set { base["toType"] = value; } 19 | } 20 | 21 | [ConfigurationProperty("defaultProperties")] 22 | public DIDefaultPropConfigList DefaultProperties 23 | { 24 | get { return (DIDefaultPropConfigList)base["defaultProperties"]; } 25 | set { base["defaultProperties"] = value; } 26 | } 27 | 28 | [ConfigurationProperty("constructorArguments")] 29 | public DIConstructorArgConfigList ConstructorArguments 30 | { 31 | get { return (DIConstructorArgConfigList)base["constructorArguments"]; } 32 | set { base["constructorArguments"] = value; } 33 | } 34 | 35 | [ConfigurationProperty("asSingleton")] 36 | public bool AsSingleton 37 | { 38 | get { return (bool)base["asSingleton"]; } 39 | set { base["asSingleton"] = value; } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Configuration/DIConfigList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Configuration; 3 | 4 | namespace Orders.com.Web.MVC.Configuration 5 | { 6 | public class DIConfigList : ConfigurationElementCollection, IEnumerable 7 | { 8 | #region ConfigurationElementCollection 9 | protected override ConfigurationElement CreateNewElement() 10 | { 11 | return new DIConfig(); 12 | } 13 | 14 | protected override object GetElementKey(ConfigurationElement element) 15 | { 16 | return ((DIConfig)element).FromType; 17 | } 18 | #endregion 19 | 20 | #region IEnumerable 21 | public new IEnumerator GetEnumerator() 22 | { 23 | return GetAll().GetEnumerator(); 24 | } 25 | #endregion 26 | 27 | public DIConfig this[int index] 28 | { 29 | get { return (DIConfig)BaseGet(index); } 30 | } 31 | 32 | new public DIConfig this[string name] 33 | { 34 | get { return (DIConfig)BaseGet(name); } 35 | } 36 | 37 | public void Add(DIConfig entry) 38 | { 39 | this.BaseAdd(entry); 40 | } 41 | 42 | public IEnumerable GetAll() 43 | { 44 | for (int i = 0; i < this.Count; i++) 45 | yield return this[i]; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Configuration/DIConfigSection.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace Orders.com.Web.MVC.Configuration 4 | { 5 | public class DIConfigSection : ConfigurationSection 6 | { 7 | [ConfigurationProperty("bindings")] 8 | public DIConfigList Bindings 9 | { 10 | get { return (DIConfigList)base["bindings"]; } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Configuration/DIConstructorArgConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace Orders.com.Web.MVC.Configuration 4 | { 5 | public class DIConstructorArgConfig : ConfigurationElement 6 | { 7 | [ConfigurationProperty("argumentName")] 8 | public string ArgumentName 9 | { 10 | get { return (string)base["argumentName"]; } 11 | set { base["argumentName"] = value; } 12 | } 13 | 14 | [ConfigurationProperty("value")] 15 | public string Value 16 | { 17 | get { return (string)base["value"]; } 18 | set { base["value"] = value; } 19 | } 20 | 21 | [ConfigurationProperty("type")] 22 | public string Type 23 | { 24 | get { return (string)base["type"]; } 25 | set { base["type"] = value; } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Configuration/DIDefaultPropConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | 3 | namespace Orders.com.Web.MVC.Configuration 4 | { 5 | public class DIDefaultPropConfig : ConfigurationElement 6 | { 7 | [ConfigurationProperty("propertyName")] 8 | public string PropertyName 9 | { 10 | get { return (string)base["propertyName"]; } 11 | set { base["propertyName"] = value; } 12 | } 13 | 14 | [ConfigurationProperty("value")] 15 | public string Value 16 | { 17 | get { return (string)base["value"]; } 18 | set { base["value"] = value; } 19 | } 20 | 21 | [ConfigurationProperty("type")] 22 | public string Type 23 | { 24 | get { return (string)base["type"]; } 25 | set { base["type"] = value; } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Controllers/CategoriesController.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.Web.MVC.ViewModels; 2 | using Orders.com.BLL.Domain; 3 | using Orders.com.BLL.Services; 4 | using System.Web.Mvc; 5 | 6 | namespace Orders.com.Web.MVC.Controllers 7 | { 8 | public class CategoriesController : ControllerBase 9 | { 10 | public CategoriesController(ICategoryService service) : base(service) 11 | { 12 | } 13 | 14 | [HttpPost, ActionName("Delete")] 15 | [ValidateAntiForgeryToken] 16 | public override ActionResult DeleteConfirmed(long id) 17 | { 18 | var result = _service.DeleteCommand(id).Execute(); 19 | if (result.Success) 20 | return RedirectToAction("Index"); 21 | else 22 | { 23 | var category = _service.GetByIDCommand(id).Execute().Value; 24 | return HandleFailedResult(new CategoryViewModel { Entity = category }, result); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Controllers/HomeController.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 Orders.com.Web.MVC.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | return View(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Controllers/InventoryItemsController.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.BLL.Services; 3 | using Orders.com.Web.MVC.ViewModels; 4 | using Peasy.Exception; 5 | using System.Collections.Generic; 6 | using System.ComponentModel.DataAnnotations; 7 | using System.Linq; 8 | using System.Web.Mvc; 9 | 10 | namespace Orders.com.Web.MVC.Controllers 11 | { 12 | public class InventoryItemsController : ControllerBase 13 | { 14 | private IProductService _productService; 15 | private IEnumerable _products; 16 | 17 | public InventoryItemsController(IInventoryItemService service, IProductService productService) : base(service) 18 | { 19 | _productService = productService; 20 | } 21 | 22 | protected override InventoryItemViewModel ConfigureVM(InventoryItemViewModel vm) 23 | { 24 | vm.ProductName = Products.First(p => p.ProductID == vm.ProductID).Name; 25 | return vm; 26 | } 27 | 28 | public override ActionResult Edit(InventoryItemViewModel vm) 29 | { 30 | try 31 | { 32 | return base.Edit(vm); 33 | } 34 | catch (ConcurrencyException ex) 35 | { 36 | ModelState.AddModelError("", ex.Message); 37 | return View(ConfigureVM(vm)); 38 | } 39 | } 40 | 41 | private IEnumerable Products 42 | { 43 | get 44 | { 45 | if (_products == null) 46 | { 47 | _products = _productService.GetAllCommand().Execute().Value; 48 | } 49 | return _products; 50 | } 51 | } 52 | 53 | [HttpGet] 54 | public ActionResult Product(int id) 55 | { 56 | var service = _service as IInventoryItemService; 57 | var inventoryItem = service.GetByProductCommand(id).Execute().Value; 58 | return Json(inventoryItem, JsonRequestBehavior.AllowGet); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/DTCTransactionContext.cs: -------------------------------------------------------------------------------- 1 | using Peasy; 2 | using System; 3 | using System.Threading.Tasks; 4 | using System.Transactions; 5 | 6 | namespace Orders.com.Web.MVC 7 | { 8 | public class DTCTransactionContext : ITransactionContext 9 | { 10 | public void Execute(Action codeToRunWithinTransaction) 11 | { 12 | using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, new System.TimeSpan(0, 5, 0))) 13 | { 14 | codeToRunWithinTransaction(); 15 | transactionScope.Complete(); 16 | } 17 | } 18 | 19 | public T Execute(Func codeToRunWithinTransaction) 20 | { 21 | using (var transactionScope = new TransactionScope()) 22 | { 23 | var result = codeToRunWithinTransaction(); 24 | transactionScope.Complete(); 25 | return result; 26 | } 27 | } 28 | 29 | public async Task ExecuteAsync(Func> codeToRunWithinTransaction) 30 | { 31 | using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 32 | { 33 | var result = await codeToRunWithinTransaction(); 34 | transactionScope.Complete(); 35 | return result; 36 | } 37 | } 38 | 39 | public async Task ExecuteAsync(Func codeToRunWithinTransaction) 40 | { 41 | using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)) 42 | { 43 | await codeToRunWithinTransaction(); 44 | transactionScope.Complete(); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Orders.com.Web.MVC.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 Orders.com.Web.MVC 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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 Orders.com.Web.MVC.Models 8 | { 9 | // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://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 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/OrdersDotComDataInitializer.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using Orders.com.DAL.EF; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Orders.com.Web.MVC 7 | { 8 | public class OrdersDotComDataInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges 9 | { 10 | protected override void Seed(OrdersDotComContext context) 11 | { 12 | var customers = new List 13 | { 14 | new Customer { Name = "Jimi Hendrix", CreatedDatetime = DateTime.Now }, 15 | new Customer { Name = "David Gilmour", CreatedDatetime = DateTime.Now }, 16 | new Customer { Name = "James Page", CreatedDatetime = DateTime.Now } 17 | }; 18 | 19 | customers.ForEach(s => context.Customers.Add(s)); 20 | context.SaveChanges(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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("Orders.com.Web.MVC")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Orders.com.Web.MVC")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 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("0c16781e-b5ca-493a-a9b4-c1a9ef4b56e7")] 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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Scripts/OrderItems.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | var quantity = $("#Quantity"); 3 | var price = $("#Price"); 4 | var priceDiv = $("#price"); 5 | var amount = $("#amount"); 6 | var categories = $("#CategoryID"); 7 | var products = $("#ProductID"); 8 | var inStock = $("#inStock"); 9 | 10 | if (priceDiv.text()) { 11 | priceDiv.text(USD(parseFloat(priceDiv.text()))); 12 | } 13 | 14 | if (amount.text()) { 15 | amount.text(USD(parseFloat(amount.text()))); 16 | } 17 | 18 | quantity.keyup(function() { 19 | amount.text(USD(quantity.val() * price.val())); 20 | }); 21 | 22 | categories.change(function () { 23 | var categoryID = categories.val(); 24 | $.getJSON("/products/category/" + categoryID, function (data) { 25 | var items = ''; 26 | $.each(data, function (i, state) { 27 | console.log(state); 28 | items += ""; 29 | }); 30 | products.html(items); 31 | }); 32 | }); 33 | 34 | products.change(function () { 35 | var productID = products.val(); 36 | $.getJSON("/inventoryitems/product/" + productID, function (data) { 37 | inStock.text(data.QuantityOnHand); 38 | }); 39 | $.getJSON("/products/product/" + productID, function (data) { 40 | price.val(data.Price); 41 | priceDiv.html(USD(data.Price)); 42 | amount.text(USD(quantity.val() * price.val())); 43 | }); 44 | }); 45 | 46 | function USD(value) { 47 | return value.toLocaleString("en-US", {style: "currency", currency: "USD", minimumFractionDigits: 2}); 48 | } 49 | }); -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Scripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.Web.MVC/Scripts/_references.js -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Owin; 2 | using Owin; 3 | 4 | [assembly: OwinStartupAttribute(typeof(Orders.com.Web.MVC.Startup))] 5 | namespace Orders.com.Web.MVC 6 | { 7 | public partial class Startup 8 | { 9 | public void Configuration(IAppBuilder app) 10 | { 11 | ConfigureAuth(app); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/ViewModels/CategoryViewModel.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | 3 | namespace Orders.com.Web.MVC.ViewModels 4 | { 5 | public class CategoryViewModel : ViewModel 6 | { 7 | public long ID 8 | { 9 | get { return Entity.ID; } 10 | set { Entity.ID = value; } 11 | } 12 | 13 | public string Name 14 | { 15 | get { return Entity.Name; } 16 | set { Entity.Name = value; } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/ViewModels/CustomerViewModel.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | 3 | namespace Orders.com.Web.MVC.ViewModels 4 | { 5 | public class CustomerViewModel : ViewModel 6 | { 7 | public long ID 8 | { 9 | get { return Entity.ID; } 10 | set { Entity.ID = value; } 11 | } 12 | 13 | public string Name 14 | { 15 | get { return Entity.Name; } 16 | set { Entity.Name = value; } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/ViewModels/InventoryItemViewModel.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Orders.com.Web.MVC.ViewModels 5 | { 6 | public class InventoryItemViewModel : ViewModel 7 | { 8 | public long ID 9 | { 10 | get { return Entity.ID; } 11 | set { Entity.ID = value; } 12 | } 13 | 14 | [Display(Name ="Name")] 15 | public string ProductName { get; set; } 16 | 17 | [Display(Name ="Quantity")] 18 | public decimal QuantityOnHand 19 | { 20 | get { return Entity.QuantityOnHand; } 21 | set { Entity.QuantityOnHand = value; } 22 | } 23 | 24 | public long ProductID 25 | { 26 | get { return Entity.ProductID; } 27 | set { Entity.ProductID = value; } 28 | } 29 | 30 | public string Version 31 | { 32 | get { return Entity.Version; } 33 | set { Entity.Version = value; } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/ViewModels/OrderViewModel.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using System; 3 | using System.Linq; 4 | using System.Collections.Generic; 5 | using System.ComponentModel.DataAnnotations; 6 | using Orders.com.BLL.Extensions; 7 | 8 | namespace Orders.com.Web.MVC.ViewModels 9 | { 10 | public class OrderViewModel : ViewModel 11 | { 12 | public string CustomerName { get; set; } 13 | 14 | public long CustomerID 15 | { 16 | get { return Entity.CustomerID; } 17 | set { Entity.CustomerID = value; } 18 | } 19 | 20 | public DateTime OrderDate 21 | { 22 | get { return Entity.OrderDate; } 23 | set { Entity.OrderDate = value; } 24 | } 25 | 26 | [DisplayFormat(DataFormatString = "{0:c}")] 27 | public decimal? Total 28 | { 29 | get { return OrderItems?.Sum(i => i.Amount); } 30 | } 31 | 32 | public long ID 33 | { 34 | get { return Entity.ID; } 35 | set { Entity.ID = value; } 36 | } 37 | 38 | public Customer AssociatedCustomer 39 | { 40 | get 41 | { 42 | return Customers.FirstOrDefault(c => c.CustomerID == CustomerID); 43 | } 44 | } 45 | 46 | public bool? HasUnsubmittedItems 47 | { 48 | get { return OrderItems?.Any(i => i.Entity.OrderStatus().CanSubmit); } 49 | } 50 | 51 | public bool? HasShippedItems 52 | { 53 | get { return OrderItems?.Any(i => i.Entity.OrderStatus().IsShipped); } 54 | } 55 | 56 | public IEnumerable OrderItems { get; set; } 57 | 58 | public IEnumerable Customers { get; set; } 59 | } 60 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/ViewModels/ProductViewModel.cs: -------------------------------------------------------------------------------- 1 | using Orders.com.BLL.Domain; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Orders.com.Web.MVC.ViewModels 6 | { 7 | public class ProductViewModel : ViewModel 8 | { 9 | public long ID 10 | { 11 | get { return Entity.ID; } 12 | set { Entity.ID = value; } 13 | } 14 | 15 | public string Name 16 | { 17 | get { return Entity.Name; } 18 | set { Entity.Name = value; } 19 | } 20 | 21 | public string Description 22 | { 23 | get { return Entity.Description; } 24 | set { Entity.Description = value; } 25 | } 26 | 27 | public long CategoryID 28 | { 29 | get { return Entity.CategoryID; } 30 | set { Entity.CategoryID = value; } 31 | } 32 | 33 | public decimal? Price 34 | { 35 | get { return Entity.Price; } 36 | set { Entity.Price = value; } 37 | } 38 | 39 | public IEnumerable Categories 40 | { 41 | get; set; 42 | } 43 | 44 | public Category AssociatedCategory 45 | { 46 | get 47 | { 48 | return Categories.FirstOrDefault(c => c.CategoryID == Entity.CategoryID); 49 | } 50 | } 51 | 52 | //public bool Save() 53 | //{ 54 | // var result = _service.InsertCommand(Entity).Execute(); 55 | // if (result.Success) 56 | // { 57 | // Entity = result.Value; 58 | // return true; 59 | // } 60 | // else 61 | // { 62 | // Errors = result.Errors; 63 | // return false; 64 | // } 65 | //} 66 | } 67 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/ViewModels/ViewModel.cs: -------------------------------------------------------------------------------- 1 | namespace Orders.com.Web.MVC.ViewModels 2 | { 3 | public class ViewModel where T : new() 4 | { 5 | public ViewModel() 6 | { 7 | Entity = new T(); 8 | } 9 | 10 | public T Entity { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/ConfirmEmail.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Confirm Email"; 3 | } 4 | 5 |

@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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/ExternalLoginConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/ExternalLoginFailure.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Login Failure"; 3 | } 4 | 5 |
6 |

@ViewBag.Title.

7 |

Unsuccessful login with service.

8 |
9 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | 35 |
36 |
37 | } 38 | 39 | @section Scripts { 40 | @Scripts.Render("~/bundles/jqueryval") 41 | } 42 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/ResetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/SendCode.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/VerifyCode.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Account/_ExternalLoginsListPartial.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Categories/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.CategoryViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Create"; 5 | } 6 | 7 |

Create Category

8 | 9 | @using (Html.BeginForm()) 10 | { 11 | @Html.AntiForgeryToken() 12 | 13 |
14 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 15 |
16 | @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-1" }) 17 |
18 | @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) 19 | @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) 20 |
21 |
22 | 23 |
24 |
25 | | 26 | @Html.ActionLink("Back to List", "Index") 27 |
28 |
29 |
30 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Categories/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.CategoryViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Delete"; 5 | } 6 | 7 |

Delete Category

8 | 9 |

Are you sure you want to delete this?

10 |
11 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 12 | 13 |
14 | @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-1" }) 15 |
16 | @Html.DisplayFor(model => model.Name) 17 |
18 |
19 | 20 | @using (Html.BeginForm()) { 21 | @Html.AntiForgeryToken() 22 | 23 |
24 | | 25 | @Html.ActionLink("Back to List", "Index") 26 |
27 | } 28 |
29 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Categories/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.CategoryViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Edit"; 5 | } 6 | 7 |

Edit Category

8 | 9 | @using (Html.BeginForm()) 10 | { 11 | @Html.AntiForgeryToken() 12 | 13 |
14 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 15 | @Html.HiddenFor(model => model.ID) 16 | 17 |
18 | @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-1" }) 19 |
20 | @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) 21 | @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) 22 |
23 |
24 | 25 |
26 |
27 | | 28 | @Html.ActionLink("Back to List", "Index") 29 |
30 |
31 |
32 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Categories/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Index"; 5 | } 6 | 7 |

Categories

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.Name) 16 |
23 | @Html.DisplayFor(modelItem => item.Name) 24 | 26 | @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | 27 | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) 28 |
33 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Customers/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.CustomerViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Create"; 5 | } 6 | 7 |

Create Customer

8 | 9 | @using (Html.BeginForm()) 10 | { 11 | @Html.AntiForgeryToken() 12 | 13 |
14 |
15 | @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-1" }) 16 |
17 | @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) 18 | @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) 19 |
20 |
21 | 22 |
23 |
24 | | 25 | @Html.ActionLink("Back to List", "Index") 26 |
27 |
28 |
29 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Customers/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.CustomerViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Delete"; 5 | } 6 | 7 |

Delete Customer

8 | 9 |

Are you sure you want to delete this?

10 |
11 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 12 | 13 |
14 | @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-1" }) 15 |
16 | @Html.DisplayFor(model => model.Name) 17 |
18 |
19 | 20 | @using (Html.BeginForm()) { 21 | @Html.AntiForgeryToken() 22 | 23 |
24 | | 25 | @Html.ActionLink("Back to List", "Index") 26 |
27 | } 28 |
29 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Customers/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.CustomerViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Edit"; 5 | } 6 | 7 |

Edit Customer

8 | 9 | @using (Html.BeginForm()) 10 | { 11 | @Html.AntiForgeryToken() 12 | 13 |
14 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 15 | @Html.HiddenFor(model => model.ID) 16 | @Html.Hidden("Test", @Newtonsoft.Json.JsonConvert.SerializeObject(Model)) 17 | 18 |
19 | @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-1" }) 20 |
21 | @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) 22 | @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) 23 |
24 |
25 | 26 |
27 |
28 | | 29 | @Html.ActionLink("Back to List", "Index") 30 |
31 |
32 |
33 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Customers/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Index"; 5 | } 6 | 7 |

Customers

8 | 9 |

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

12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | @foreach (var item in Model) { 22 | 23 | 26 | 30 | 31 | } 32 | 33 |
16 | @Html.DisplayNameFor(model => model.Name) 17 |
24 | @Html.DisplayFor(modelItem => item.Name) 25 | 27 | @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | 28 | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) 29 |
34 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Home Page"; 3 | } 4 | 5 |
6 |

Orders.com

7 |
8 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/InventoryItems/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.InventoryItemViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Edit"; 5 | } 6 | 7 |

Edit Inventory

8 | 9 | @using (Html.BeginForm()) 10 | { 11 | @Html.AntiForgeryToken() 12 | 13 |
14 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 15 | @Html.HiddenFor(model => model.ID) 16 | @Html.HiddenFor(model => model.ProductID) 17 | @Html.HiddenFor(model => model.Version) 18 | 19 |
20 | @Html.LabelFor(model => model.ProductName, htmlAttributes: new { @class = "control-label col-md-1" }) 21 |
22 | @Html.DisplayFor(model => model.ProductName, new { htmlAttributes = new { @class = "form-control" } }) 23 |
24 |
25 | 26 |
27 | @Html.LabelFor(model => model.QuantityOnHand, htmlAttributes: new { @class = "control-label col-md-1" }) 28 |
29 | @Html.EditorFor(model => model.QuantityOnHand, new { htmlAttributes = new { @class = "form-control" } }) 30 | @Html.ValidationMessageFor(model => model.QuantityOnHand, "", new { @class = "text-danger" }) 31 |
32 |
33 | 34 |
35 |
36 | | 37 | @Html.ActionLink("Back to List", "Index") 38 |
39 |
40 | 41 |
42 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/InventoryItems/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | @{ 3 | ViewBag.Title = "Index"; 4 | } 5 | 6 |

Inventory

7 | 8 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | @foreach (var item in Model) { 20 | 21 | 24 | 27 | 30 | 31 | } 32 | 33 |
11 | @Html.DisplayNameFor(model => model.ProductName) 12 | 14 | @Html.DisplayNameFor(model => model.QuantityOnHand) 15 |
22 | @Html.DisplayFor(modelItem => item.ProductName) 23 | 25 | @Html.DisplayFor(modelItem => item.QuantityOnHand) 26 | 28 | @Html.ActionLink("Edit", "Edit", new { id=item.ID }) 29 |
34 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Manage/AddPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Manage/ChangePassword.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Manage/SetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Manage/VerifyPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/OrderItems/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.OrderItemViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Delete"; 5 | } 6 | 7 |

Delete Item

8 | 9 |

Are you sure you want to delete this?

10 |
11 | 12 |
13 | 14 |
15 | @Html.DisplayFor(model => model.AssociatedCategory.Name) 16 |
17 |
18 | 19 |
20 | 21 |
22 | @Html.DisplayFor(model => model.AssociatedProduct.Name) 23 |
24 |
25 | 26 |
27 | 28 |
29 | @Html.DisplayFor(model => model.Price) 30 |
31 |
32 | 33 |
34 | 35 |
36 | @Html.DisplayFor(model => model.Quantity) 37 |
38 |
39 | 40 |
41 | 42 |
43 | @Html.DisplayFor(model => model.Amount) 44 |
45 |
46 | 47 |
48 | 49 |
50 | @Html.DisplayFor(model => model.Status) 51 |
52 |
53 | 54 | 55 | @using (Html.BeginForm()) 56 | { 57 | @Html.AntiForgeryToken() 58 | 59 |
60 | | 61 | @Html.ActionLink("Back to List", "Edit", "Orders", new { id = Model.OrderID }, null) 62 |
63 | } 64 |
65 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Orders/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.OrderViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Edit"; 5 | } 6 | 7 |

Create Order

8 | 9 | @using (Html.BeginForm()) 10 | { 11 | @Html.AntiForgeryToken() 12 | 13 |
14 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 15 | @Html.HiddenFor(model => model.ID) 16 | 17 |
18 | 19 |
20 | @Html.DropDownListFor(model => model.CustomerID, new SelectList(Model.Customers, "CustomerID", "Name"), "-- select one --", new { @class = "form-control" }) 21 | @Html.ValidationMessageFor(model => model.CustomerID, "", new { @class = "text-danger" }) 22 |
23 |
24 | 25 |
26 |
27 | | 28 | @Html.ActionLink("Back to List", "Index") 29 |
30 |
31 | 32 |
33 | } -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Orders/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.OrderViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Delete"; 5 | } 6 | 7 |

Delete Order

8 | 9 |

Are you sure you want to delete this?

10 | 11 |
12 | 13 |
14 | 15 |
16 | @Html.DisplayFor(model => model.ID) 17 |
18 |
19 | 20 |
21 | 22 |
23 | @Html.DisplayFor(model => model.AssociatedCustomer.Name) 24 |
25 |
26 | 27 |
28 | 29 |
30 | @Html.DisplayFor(model => model.Total) 31 |
32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | @foreach (var item in Model.OrderItems) 43 | { 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | } 52 | 53 |
ProductPriceQuantityAmountStatus
@Html.DisplayFor(modelItem => item.ProductName)@Html.DisplayFor(modelItem => item.Price)@Html.DisplayFor(modelItem => item.Quantity)@Html.DisplayFor(modelItem => item.Amount)@Html.DisplayFor(modelItem => item.Status)
54 | 55 |
56 | @using (Html.BeginForm()) 57 | { 58 | @Html.AntiForgeryToken() 59 | 60 |
61 | | 62 | @Html.ActionLink("Back to List", "Index") 63 |
64 | } 65 | 66 |
67 |
-------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Orders/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | @{ 3 | ViewBag.Title = "Index"; 4 | } 5 | 6 |

Orders

7 | 8 |

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

11 | 12 | 13 | 14 | 17 | 20 | 23 | 26 | 27 | 28 | 29 | @foreach (var item in Model) { 30 | 31 | 34 | 37 | 40 | 43 | 50 | 51 | } 52 | 53 |
15 | @Html.DisplayNameFor(model => model.OrderDate) 16 | 18 | @Html.DisplayNameFor(model => model.CustomerName) 19 | 21 | @Html.DisplayNameFor(model => model.Total) 22 | 24 | @Html.DisplayNameFor(model => model.Status) 25 |
32 | @Html.DisplayFor(modelItem => item.OrderDate) 33 | 35 | @Html.DisplayFor(modelItem => item.CustomerName) 36 | 38 | @Html.DisplayFor(modelItem => item.Total) 39 | 41 | @Html.DisplayFor(modelItem => item.Status) 42 | 44 | @Html.ActionLink("Edit", "Edit", new { id=item.OrderID }) 45 | @if (!item.HasShippedItems) 46 | { 47 | | @Html.ActionLink("Delete", "Delete", new { id=item.OrderID }) 48 | } 49 |
54 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Products/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Orders.com.Web.MVC.ViewModels.ProductViewModel 2 | 3 | 4 | @{ 5 | ViewBag.Title = "Delete"; 6 | } 7 | 8 |

Delete Product

9 | 10 |

Are you sure you want to delete this?

11 |
12 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 13 |
14 | @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-1" }) 15 |
16 | @Html.DisplayFor(model => model.Name) 17 |
18 |
19 |
20 | @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-1" }) 21 |
22 | @Html.DisplayFor(model => model.Description) 23 |
24 |
25 |
26 | @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-1" }) 27 |
28 | @Html.DisplayFor(model => model.Price) 29 |
30 |
31 |
32 | @Html.LabelFor(model => model.CategoryID, htmlAttributes: new { @class = "control-label col-md-1" }) 33 |
34 | @Html.DisplayFor(model => model.AssociatedCategory.Name) 35 |
36 |
37 | 38 | @using (Html.BeginForm()) { 39 | @Html.AntiForgeryToken() 40 | 41 |
42 | | 43 | @Html.ActionLink("Back to List", "Index") 44 |
45 | } 46 |
47 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Products/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Index"; 5 | } 6 | 7 |

Products

8 | 9 |

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

12 | 13 | 14 | 17 | 20 | 23 | 26 | 27 | 28 | 29 | @foreach (var item in Model) { 30 | 31 | 34 | 37 | 40 | 43 | 47 | 48 | } 49 | 50 |
15 | @Html.DisplayNameFor(model => model.Name) 16 | 18 | @Html.DisplayNameFor(model => model.Description) 19 | 21 | @Html.DisplayNameFor(model => model.Price) 22 | 24 | Category 25 |
32 | @Html.DisplayFor(modelItem => item.Name) 33 | 35 | @Html.DisplayFor(modelItem => item.Description) 36 | 38 | @Html.DisplayFor(modelItem => item.Price) 39 | 41 | @Html.DisplayFor(modelItem => item.AssociatedCategory.Name) 42 | 44 | @Html.ActionLink("Edit", "Edit", new { id=item.ID }) | 45 | @Html.ActionLink("Delete", "Delete", new { id=item.ID }) 46 |
51 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Shared/_ErrorsList.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @if (Model.Any()) 4 | { 5 |
    6 | @foreach (var error in Model) 7 | { 8 |
  • @error.ErrorMessage
  • 9 | } 10 |
11 | } 12 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - Orders.com 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 12 | 34 |
35 | @RenderBody() 36 |
37 |
38 |

© @DateTime.Now.Year - Orders.com

39 |
40 |
41 | 42 | @Scripts.Render("~/bundles/jquery") 43 | @Scripts.Render("~/bundles/bootstrap") 44 | @RenderSection("scripts", required: false) 45 | 46 | 47 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/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 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Orders.com.Web.MVC/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.Web.MVC/favicon.ico -------------------------------------------------------------------------------- /Orders.com.Web.MVC/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.Web.MVC/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Orders.com.Web.MVC/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.Web.MVC/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Orders.com.Web.MVC/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peasy/Peasy.NET-Samples/0236d192944675c123af46ef72321a7cc3517ab5/Orders.com.Web.MVC/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Package.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Package 5 | 1.0.0 6 | Aaron 7 | Aaron 8 | http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE 9 | http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE 10 | http://ICON_URL_HERE_OR_DELETE_THIS_LINE 11 | false 12 | Package description 13 | Summary of changes made in this release of the package. 14 | Copyright 2015 15 | Tag1 Tag2 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | 2 | Order State History - OrderStateHistory dto, service, etc. Maybe remove order state change dates from OrderItem? 3 | 4 | Fix Inventory view bug - go to product view, delete a product, go to the inventory view, an exception is raised 5 | 6 | The validation and business rules infrastructure is a bit smelly. Figure out how to more easily create business rules and validation rules, or unify the interface and no longer expose ValidationResult, but use IRule and ValidationResult under the hood. Look at some of the commands GetError() methods to see examples of why things are smelly. 7 | 8 | BusinessBase - add concurrency business rule in update rather than throw concurrency exception? 9 | 10 | Do we need GetValidationResult methods for get, getall, and delete? IE, look at InventoryService.DecrementQOH and the usage of creating a validation rule. Does this even make sense? Seems like an exception should be thrown if supplied values aren't correct? Think about this one.... maybe i originally designed it this way to support binding values? 11 | 12 | 13 | 14 | Change Command.Execute(Async) to be virtual and not abstract 15 | 16 | Create EF project 17 | 18 | Create Web API project 19 | 20 | Create Restful Proxies 21 | -Ensure that the error message displays properly in WPF app when an item no longer exists 22 | 23 | Create SPA web app consumer 24 | 25 | Create tests for VM's and other framework - adding tests around VM's will ensure that future contributors who change the framework won't break the WPF app, revealing flawed logic 26 | 27 | Add dynamic DI support to consumer projects 28 | 29 | 30 | New Nuget releases 31 | 32 | Figure out versioning strategy - branches or tags 33 | 34 | Move sample projects into a different directory and remove project references, adding nuget refs instead 35 | 36 | Clean up ApiControllerBase - add etag support, cache control, last modified, etc. 37 | 38 | Store in-memory proxies globally in webapi project 39 | 40 | 41 | 42 | 43 | --------------------------------------------------------------------------------