├── Blip.Web ├── Views │ ├── _ViewStart.cshtml │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Customer │ │ ├── Index.cshtml │ │ └── Create.cshtml │ ├── Web.config │ └── Order │ │ └── Index.cshtml ├── favicon.ico ├── Global.asax ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── App_Start │ ├── FilterConfig.cs │ ├── RouteConfig.cs │ └── BundleConfig.cs ├── Content │ └── Site.css ├── Global.asax.cs ├── Controllers │ ├── HomeController.cs │ ├── OrderController.cs │ └── CustomerController.cs ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── packages.config ├── Scripts │ ├── respond.min.js │ ├── respond.matchmedia.addListener.min.js │ ├── jquery.validate.unobtrusive.min.js │ ├── respond.js │ └── respond.matchmedia.addListener.js ├── Web.config ├── ApplicationInsights.config └── Blip.Web.csproj ├── Blip.Data ├── Migrations │ ├── Configuration.cs │ ├── 201709021326086_OrdersItems.Designer.cs │ ├── 201708222251192_InitialMigration.Designer.cs │ ├── 201708222251192_InitialMigration.cs │ ├── 201709021326086_OrdersItems.cs │ ├── 201708222251192_InitialMigration.resx │ └── 201709021326086_OrdersItems.resx ├── Context │ └── Context.cs ├── packages.config ├── Geographies │ ├── CountriesRepository.cs │ └── RegionsRepository.cs ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── Orders │ └── OrdersRepository.cs ├── App.config ├── Customer │ └── CustomersRepository.cs └── Blip.Data.csproj ├── Blip.Common ├── packages.config ├── Formatting │ ├── Attributes.cs │ └── Phones.cs ├── App.config ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── Extensions │ └── EnumEx.cs └── Blip.Common.csproj ├── Blip.Entities ├── Geographies │ ├── Country.cs │ └── Region.cs ├── Orders.ViewModels │ ├── OrderDisplayViewModel.cs │ └── CustomerOrdersListViewModel.cs ├── Customers.ViewModels │ ├── CustomerDisplayViewModel.cs │ └── CustomerEditViewModel.cs ├── packages.config ├── Items │ └── Item.cs ├── Orders │ ├── OrderItem.cs │ └── Order.cs ├── Customers │ └── Customer.cs ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── App.config └── Blip.Entities.csproj ├── LICENSE ├── BlipBinding.sln ├── CONTRIBUTING.md ├── .gitattributes ├── Readme.md └── .gitignore /Blip.Web/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Blip.Web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajsaulsberry/BlipBinding/HEAD/Blip.Web/favicon.ico -------------------------------------------------------------------------------- /Blip.Web/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="BlipProjects.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Blip.Data/Migrations/Configuration.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajsaulsberry/BlipBinding/HEAD/Blip.Data/Migrations/Configuration.cs -------------------------------------------------------------------------------- /Blip.Web/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajsaulsberry/BlipBinding/HEAD/Blip.Web/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Blip.Web/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajsaulsberry/BlipBinding/HEAD/Blip.Web/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Blip.Web/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajsaulsberry/BlipBinding/HEAD/Blip.Web/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Blip.Web/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ajsaulsberry/BlipBinding/HEAD/Blip.Web/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /Blip.Web/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /Blip.Common/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Blip.Web/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /Blip.Web/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace BlipProjects 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Blip.Entities/Geographies/Country.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Blip.Entities.Geographies 5 | { 6 | public class Country 7 | { 8 | [Key] 9 | [MaxLength(3)] 10 | public string Iso3 { get; set; } 11 | 12 | [Required] 13 | [MaxLength(50)] 14 | public string CountryNameEnglish { get; set; } 15 | 16 | public virtual IEnumerable Regions { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /Blip.Entities/Geographies/Region.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Blip.Entities.Geographies 4 | { 5 | public class Region 6 | { 7 | [Key] 8 | [MaxLength(3)] 9 | public string RegionCode { get; set; } 10 | 11 | [Required] 12 | [MaxLength(3)] 13 | public string Iso3 { get; set; } 14 | 15 | [Required] 16 | public string RegionNameEnglish { get; set; } 17 | 18 | public virtual Country Country { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /Blip.Web/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /Blip.Entities/Orders.ViewModels/OrderDisplayViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Blip.Entities.Orders.ViewModels 5 | { 6 | public class OrderDisplayViewModel 7 | { 8 | public Guid CustomerID { get; set; } 9 | 10 | [Display(Name = "Order Number")] 11 | public Guid OrderID { get; set; } 12 | 13 | [Display(Name = "Order Date")] 14 | public DateTime OrderDate { get; set; } 15 | 16 | [Display(Name = "PO / Description")] 17 | public string Description { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Blip.Web/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 | -------------------------------------------------------------------------------- /Blip.Entities/Customers.ViewModels/CustomerDisplayViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Blip.Entities.Customers.ViewModels 5 | { 6 | public class CustomerDisplayViewModel 7 | { 8 | [Display(Name = "Customer Number")] 9 | public Guid CustomerID { get; set; } 10 | 11 | [Display(Name = "Customer Name")] 12 | public string CustomerName { get; set; } 13 | 14 | [Display(Name = "Country")] 15 | public string CountryName { get; set; } 16 | 17 | [Display(Name = "State / Province / Region")] 18 | public string RegionName { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /Blip.Entities/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Blip.Web/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 BlipProjects 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 | -------------------------------------------------------------------------------- /Blip.Web/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 BlipProjects 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 | -------------------------------------------------------------------------------- /Blip.Web/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 BlipProjects.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public ActionResult Index() 12 | { 13 | return View(); 14 | } 15 | 16 | public ActionResult About() 17 | { 18 | ViewBag.Message = "Your application description page."; 19 | 20 | return View(); 21 | } 22 | 23 | public ActionResult Contact() 24 | { 25 | ViewBag.Message = "Your contact page."; 26 | 27 | return View(); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Blip.Entities/Orders.ViewModels/CustomerOrdersListViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace Blip.Entities.Orders.ViewModels 6 | { 7 | public class CustomerOrdersListViewModel 8 | { 9 | [Display(Name = "Customer Number")] 10 | public Guid CustomerID { get; set; } 11 | 12 | [Display(Name = "Customer Name")] 13 | public string CustomerName { get; set; } 14 | 15 | [Display(Name = "Country")] 16 | public string CountryNameEnglish { get; set; } 17 | 18 | [Display(Name = "Region")] 19 | public string RegionNameEnglish { get; set; } 20 | 21 | public List Orders { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Blip.Entities/Items/Item.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using Blip.Entities.Orders; 6 | 7 | namespace Blip.Entities.Items 8 | { 9 | public class Item 10 | { 11 | public Item() 12 | { 13 | Orders = new HashSet(); 14 | } 15 | 16 | [Key] 17 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 18 | public Guid ItemID { get; set; } 19 | 20 | [Required] 21 | [MaxLength(128)] 22 | public String Description { get; set; } 23 | 24 | public int ReorderQuantity { get; set; } 25 | 26 | public decimal MSRP { get; set; } 27 | 28 | public ICollection Orders { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Blip.Entities/Orders/OrderItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using Blip.Entities.Items; 5 | 6 | namespace Blip.Entities.Orders 7 | { 8 | public class OrderItem 9 | { 10 | [Key] 11 | [Column(Order = 0)] 12 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 13 | public virtual Guid ItemID { get; set; } 14 | 15 | [Key] 16 | [Column(Order = 1)] 17 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 18 | public virtual Guid OrderID { get; set; } 19 | 20 | public decimal Price { get; set; } 21 | 22 | public short Quantity { get; set; } 23 | 24 | public virtual Order Order { get; set; } 25 | 26 | public virtual Item Item { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Blip.Data/Context/Context.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Entity; 2 | using System.Data.Entity.ModelConfiguration.Conventions; 3 | using Blip.Entities.Customers; 4 | using Blip.Entities.Geographies; 5 | using Blip.Entities.Items; 6 | using Blip.Entities.Orders; 7 | 8 | namespace Blip.Data 9 | { 10 | public class ApplicationDbContext : DbContext 11 | { 12 | public ApplicationDbContext() : base("ApplicationDbContext") 13 | { 14 | 15 | } 16 | public DbSet Countries { get; set; } 17 | public DbSet Customers { get; set; } 18 | public DbSet Regions { get; set; } 19 | public DbSet Orders { get; set; } 20 | public DbSet Items { get; set; } 21 | public DbSet OrderItems { get; set; } 22 | 23 | protected override void OnModelCreating(DbModelBuilder modelBuilder) 24 | { 25 | 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Blip.Common/Formatting/Attributes.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Blip.Common.Formatting 4 | { 5 | public class Attributes 6 | { 7 | // Code from http://stackoverflow.com/questions/3548300/how-to-do-integer-model-validation-in-asp-net-mvc-2 8 | public class PosNumberNoZeroAttribute : ValidationAttribute 9 | { 10 | public override bool IsValid(object value) 11 | { 12 | if (value == null) 13 | { 14 | return true; 15 | } 16 | if (int.TryParse(value.ToString(), out int getal)) 17 | { 18 | 19 | if (getal == 0) 20 | return false; 21 | 22 | if (getal > 0) 23 | return true; 24 | } 25 | return false; 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Blip.Data/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Blip.Entities/Customers.ViewModels/CustomerEditViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.Web.Mvc; 4 | 5 | namespace Blip.Entities.Customers.ViewModels 6 | { 7 | public class CustomerEditViewModel 8 | { 9 | [Display(Name = "Customer Number")] 10 | public string CustomerID { get; set; } 11 | 12 | [Required] 13 | [Display(Name = "Customer Name")] 14 | [StringLength(75)] 15 | public string CustomerName { get; set; } 16 | 17 | [Required] 18 | [Display(Name = "Country")] 19 | public string SelectedCountryIso3 { get; set; } 20 | public IEnumerable Countries { get; set; } 21 | 22 | [Required] 23 | [Display(Name = "State / Region")] 24 | public string SelectedRegionCode { get; set; } 25 | public IEnumerable Regions { get; set; } 26 | } 27 | } -------------------------------------------------------------------------------- /Blip.Entities/Orders/Order.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using Blip.Entities.Customers; 6 | using Blip.Entities.Items; 7 | 8 | namespace Blip.Entities.Orders 9 | { 10 | public class Order 11 | { 12 | public Order() 13 | { 14 | Items = new HashSet(); 15 | } 16 | 17 | [Key] 18 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 19 | public Guid OrderID { get; set; } 20 | 21 | [Required] 22 | public Guid CustomerID { get; set; } 23 | 24 | [Required] 25 | public DateTime OrderDate { get; set; } 26 | 27 | [Required] 28 | [MaxLength(128)] 29 | public string Description { get; set; } 30 | 31 | public ICollection Items { get; set; } 32 | 33 | public virtual Customer Customer { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Blip.Data/Migrations/201709021326086_OrdersItems.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Blip.Data.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 OrdersItems : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(OrdersItems)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201709021326086_OrdersItems"; } 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 | -------------------------------------------------------------------------------- /Blip.Data/Migrations/201708222251192_InitialMigration.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Blip.Data.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.0-30225")] 10 | public sealed partial class InitialMigration : IMigrationMetadata 11 | { 12 | private readonly ResourceManager Resources = new ResourceManager(typeof(InitialMigration)); 13 | 14 | string IMigrationMetadata.Id 15 | { 16 | get { return "201708222251192_InitialMigration"; } 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 | -------------------------------------------------------------------------------- /Blip.Common/Formatting/Phones.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace Blip.Common.Formatting 5 | { 6 | public static class Phones 7 | { 8 | private static Regex digitsOnly = new Regex(@"[^\d]"); 9 | public static string CleanPhone(string phone) 10 | { 11 | if (!String.IsNullOrEmpty(phone)) 12 | { 13 | return digitsOnly.Replace(phone, ""); 14 | } 15 | else 16 | { 17 | return null; 18 | } 19 | } 20 | 21 | public static string FormatPhone(string phone) 22 | { 23 | if (!String.IsNullOrEmpty(phone)) 24 | { 25 | Int64 phoneDigits; 26 | if (Int64.TryParse(phone, out phoneDigits)) 27 | return String.Format("{0:(###) ###-####}", phoneDigits); 28 | else 29 | return null; 30 | } 31 | else 32 | { 33 | return null; 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Blip.Entities/Customers/Customer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using Blip.Entities.Geographies; 6 | using Blip.Entities.Orders; 7 | 8 | namespace Blip.Entities.Customers 9 | { 10 | public class Customer 11 | { 12 | public Customer() 13 | { 14 | Orders = new HashSet(); 15 | } 16 | 17 | [Key] 18 | [Column(Order = 0)] 19 | [DatabaseGenerated(DatabaseGeneratedOption.None)] 20 | public Guid CustomerID { get; set; } 21 | 22 | [Required] 23 | [MaxLength(128)] 24 | public string CustomerName { get; set; } 25 | 26 | [Required] 27 | [MaxLength(3)] 28 | public string CountryIso3 { get; set; } 29 | 30 | [MaxLength(3)] 31 | public string RegionCode { get; set; } 32 | 33 | public virtual Country Country { get; set; } 34 | 35 | public virtual Region Region { get; set; } 36 | 37 | public virtual ICollection Orders { get; set; } 38 | } 39 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 A. J. Saulsberry 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. 22 | -------------------------------------------------------------------------------- /Blip.Data/Geographies/CountriesRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Web.Mvc; 4 | 5 | namespace Blip.Data 6 | { 7 | public class CountriesRepository 8 | { 9 | public IEnumerable GetCountries() 10 | { 11 | using (var context = new ApplicationDbContext()) 12 | { 13 | List countries = context.Countries.AsNoTracking() 14 | .OrderBy(n => n.CountryNameEnglish) 15 | .Select(n => 16 | new SelectListItem 17 | { 18 | Value = n.Iso3.ToString(), 19 | Text = n.CountryNameEnglish 20 | }).ToList(); 21 | var countrytip = new SelectListItem() 22 | { 23 | Value = null, 24 | Text = "--- select country ---" 25 | }; 26 | countries.Insert(0, countrytip); 27 | return new SelectList(countries, "Value", "Text"); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Blip.Common/App.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Blip.Web/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Blip.Web/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace BlipProjects 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at https://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js", 24 | "~/Scripts/respond.js")); 25 | 26 | bundles.Add(new StyleBundle("~/Content/css").Include( 27 | "~/Content/bootstrap.css", 28 | "~/Content/site.css")); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Blip.Data/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Blip.Common/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Blip.Entities/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Blip.Web/Controllers/OrderController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Web.Mvc; 4 | using Blip.Data.Orders; 5 | using Blip.Entities.Orders.ViewModels; 6 | 7 | namespace BlipProjects.Controllers 8 | { 9 | public class OrderController : Controller 10 | { 11 | // GET: Order 12 | public ActionResult Index(string customerid) 13 | { 14 | if(!String.IsNullOrWhiteSpace(customerid)) 15 | { 16 | if (Guid.TryParse(customerid, out Guid customerId)) 17 | { 18 | var repo = new OrdersRepository(); 19 | var model = repo.GetCustomerOrdersDisplay(customerId); 20 | return View(model); 21 | } 22 | } 23 | return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 24 | } 25 | 26 | [HttpPost] 27 | [ValidateAntiForgeryToken] 28 | public ActionResult Index(CustomerOrdersListViewModel model) 29 | { 30 | if (ModelState.IsValid) 31 | { 32 | if (model.Orders != null) 33 | { 34 | var repo = new OrdersRepository(); 35 | repo.SaveOrders(model.Orders); 36 | } 37 | return View(model); 38 | } 39 | return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Blip.Web/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Blip.Common/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Blip.Data/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Blip.Entities/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Blip.Data/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("Blip.Data")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Blip.Data")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c8f46fa8-bef3-4592-bd57-e5e9ecfca1b9")] 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 | -------------------------------------------------------------------------------- /Blip.Web/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("BlipProjects")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("BlipProjects")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3e3496ee-1605-405a-b70a-d647b3ca9336")] 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 | -------------------------------------------------------------------------------- /Blip.Common/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("Blip.Common")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Blip.Common")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("7bc8455d-5b90-4a20-aed3-d988781494f4")] 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 | -------------------------------------------------------------------------------- /Blip.Entities/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("Blip.Entities")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Blip.Entities")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3a1ff2ca-e0aa-4e04-a082-b8fccd23f8f0")] 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 | -------------------------------------------------------------------------------- /Blip.Data/Geographies/RegionsRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Mvc; 5 | 6 | namespace Blip.Data 7 | { 8 | public class RegionsRepository 9 | { 10 | public IEnumerable GetRegions() 11 | { 12 | List regions = new List() 13 | { 14 | new SelectListItem 15 | { 16 | Value = null, 17 | Text = " " 18 | } 19 | }; 20 | return regions; 21 | } 22 | 23 | public IEnumerable GetRegions(string iso3) 24 | { 25 | if (!String.IsNullOrWhiteSpace(iso3)) 26 | { 27 | using (var context = new ApplicationDbContext()) 28 | { 29 | IEnumerable regions = context.Regions.AsNoTracking() 30 | .OrderBy(n => n.RegionNameEnglish) 31 | .Where(n => n.Iso3 == iso3) 32 | .Select(n => 33 | new SelectListItem 34 | { 35 | Value = n.RegionCode, 36 | Text = n.RegionNameEnglish 37 | }).ToList(); 38 | return new SelectList(regions, "Value", "Text"); 39 | } 40 | } 41 | return null; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Blip.Web/Views/Customer/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | ViewBag.Title = "Customer List"; 5 | } 6 | 7 |

Customer List

8 |

9 | To see the dropdown lists in action, click "Create New". 10 |

11 | 12 |

13 | @Html.ActionLink("Create New", "Create") 14 |

15 | 16 | 17 | 20 | 23 | 26 | 29 | 30 | 31 | 32 | @foreach(var item in Model) 33 | { 34 | 35 | 38 | 41 | 44 | 47 | 52 | 53 | } 54 | 55 |
18 | @Html.DisplayNameFor(model => model.CustomerID) 19 | 21 | @Html.DisplayNameFor(model => model.CustomerName) 22 | 24 | @Html.DisplayNameFor(model => model.CountryName) 25 | 27 | @Html.DisplayNameFor(model => model.RegionName) 28 |
36 | @Html.DisplayFor(modelItem => item.CustomerID) 37 | 39 | @Html.DisplayFor(modelItem => item.CustomerName) 40 | 42 | @Html.DisplayFor(modelItem => item.CountryName) 43 | 45 | @Html.DisplayFor(modelItem => item.RegionName) 46 | 48 | @Html.ActionLink("Orders", "Index", "Order", new { customerid = item.CustomerID }, null) 49 | @*@Html.ActionLink("Details", "Details", new { id = item.CustomerID }) | 50 | @Html.ActionLink("Delete", "Delete", new { id = item.CustomerID })*@ 51 |
56 | -------------------------------------------------------------------------------- /Blip.Common/Extensions/EnumEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Reflection; 4 | 5 | namespace Blip.Common.Extensions 6 | { 7 | // Code from: http://stackoverflow.com/questions/4367723/get-enum-from-description-attribute 8 | public static class EnumEx 9 | { 10 | public static string GetDescription(this Enum value) 11 | { 12 | FieldInfo field = value.GetType().GetField(value.ToString()); 13 | 14 | DescriptionAttribute attribute 15 | = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) 16 | as DescriptionAttribute; 17 | 18 | return attribute == null ? value.ToString() : attribute.Description; 19 | } 20 | 21 | public static T GetValueFromDescription(string description) 22 | { 23 | var type = typeof(T); 24 | if (!type.IsEnum) throw new InvalidOperationException(); 25 | foreach (var field in type.GetFields()) 26 | { 27 | if (Attribute.GetCustomAttribute(field, 28 | typeof(DescriptionAttribute)) is DescriptionAttribute attribute) 29 | { 30 | if (attribute.Description == description) 31 | return (T)field.GetValue(null); 32 | } 33 | else 34 | { 35 | if (field.Name == description) 36 | return (T)field.GetValue(null); 37 | } 38 | } 39 | throw new ArgumentException("Not found.", "description"); 40 | // or return default(T); 41 | } 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /Blip.Web/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 30 |
31 | @RenderBody() 32 |
33 |
34 |

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

35 |
36 |
37 | 38 | @Scripts.Render("~/bundles/jquery") 39 | @Scripts.Render("~/bundles/bootstrap") 40 | @RenderSection("scripts", required: false) 41 | 42 | 43 | -------------------------------------------------------------------------------- /Blip.Web/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Home Page"; 3 | } 4 | 5 |
6 |

ASP.NET

7 |

ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.

8 |

Learn more »

9 |
10 | 11 |
12 |
13 |

PluralSight Hack.Guides() Demos

14 |
15 |
16 |

Getting default data binding right for hierarchical views

17 |

18 | Demonstration of hierarchical forms. 19 |

20 |

Customers »

21 |
22 |
23 | 24 |
25 |
26 |

Getting started

27 |

28 | ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that 29 | enables a clean separation of concerns and gives you full control over markup 30 | for enjoyable, agile development. 31 |

32 |

Learn more »

33 |
34 |
35 |

Get more libraries

36 |

NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.

37 |

Learn more »

38 |
39 |
40 |

Web Hosting

41 |

You can easily find a web hosting company that offers the right mix of features and price for your applications.

42 |

Learn more »

43 |
44 |
-------------------------------------------------------------------------------- /Blip.Web/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 | -------------------------------------------------------------------------------- /Blip.Entities/App.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /BlipBinding.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blip.Data", "Blip.Data\Blip.Data.csproj", "{C8F46FA8-BEF3-4592-BD57-E5E9ECFCA1B9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blip.Entities", "Blip.Entities\Blip.Entities.csproj", "{3A1FF2CA-E0AA-4E04-A082-B8FCCD23F8F0}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blip.Web", "Blip.Web\Blip.Web.csproj", "{C822CC2D-7129-46F8-9CA0-A519046EB5A7}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {C8F46FA8-BEF3-4592-BD57-E5E9ECFCA1B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {C8F46FA8-BEF3-4592-BD57-E5E9ECFCA1B9}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {C8F46FA8-BEF3-4592-BD57-E5E9ECFCA1B9}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {C8F46FA8-BEF3-4592-BD57-E5E9ECFCA1B9}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {3A1FF2CA-E0AA-4E04-A082-B8FCCD23F8F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {3A1FF2CA-E0AA-4E04-A082-B8FCCD23F8F0}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {3A1FF2CA-E0AA-4E04-A082-B8FCCD23F8F0}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {3A1FF2CA-E0AA-4E04-A082-B8FCCD23F8F0}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {C822CC2D-7129-46F8-9CA0-A519046EB5A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {C822CC2D-7129-46F8-9CA0-A519046EB5A7}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {C822CC2D-7129-46F8-9CA0-A519046EB5A7}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {C822CC2D-7129-46F8-9CA0-A519046EB5A7}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {A7A90FE0-35A1-4BAE-8F21-01BB5BEEB6DA} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Blip.Web/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Thanks for taking an interest in this project. The authors hope the code in this repository and the accompanying article on [PluralSight Hack.Guides](https://www.pluralsight.com/guides) is helpful to you on your path toward greater proficiency as a developer. 4 | 5 | * See the [Readme](Readme.md) file for information about the article(s) associated with this repository. 6 | 7 | * If you have a suggestion to make the code more useful, and that suggestion takes the form of *code*, see the section on [Making Changes](#making-changes). 8 | 9 | * If you believe you have found a bug in the code, please check to see if it has previously been reported by searching for it on GitHub under [Issues](https://github.com/ajsaulsberry/BlipAjax/issues) before opening a new issue or making changes. 10 | 11 | ## Reporting issues 12 | 13 | Keep in mind that the intended use of the GitHub issue tracker for this repository is to report, discuss, and eliminate bugs in the existing code. It is not for: 14 | 15 | * Requesting help implementing or modifying the code 16 | 17 | * Reporting problems or asking questions about the article based on the code. (Use the Disqus commenting section below the article for that.) 18 | 19 | ### Making changes 20 | 21 | Keep in mind that the code in the **master** branch of the repository is used in the text of the accompanying article on PluralSight. There is no automatic link between the repository and the article, so changes to the repository that effect code used in the article will necessitate manual changes to the article as well. Such changes may in turn effect the relevance of the code to the content of the article. Exercise restraint. 22 | 23 | * If you are new to contributing to open source projects, kindly read the exellent [Open Source Contribution Etiquette](http://tirania.org/blog/archive/2010/Dec-31.htm) by Miguel de Icaza. 24 | 25 | * Fork the code and create a topic branch off **master** for your changes. 26 | 27 | * Make commits to your local repo and sync them with the origin repo on GitHub. 28 | 29 | * Commit messages should be 72 characters or less, optionally followed by a blank line and a description of the commit if more information is appropriate. 30 | 31 | * Send a pull request for your proposed changes. 32 | 33 | * Mention @ajsaulsberry in your pull request to have your proposed changes reviewed. 34 | 35 | * Do not create a pull request solely for the purpose of updating NuGet packages or other dependencies. -------------------------------------------------------------------------------- /Blip.Data/Migrations/201708222251192_InitialMigration.cs: -------------------------------------------------------------------------------- 1 | namespace Blip.Data.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class InitialMigration : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateTable( 11 | "dbo.Countries", 12 | c => new 13 | { 14 | Iso3 = c.String(nullable: false, maxLength: 3), 15 | CountryNameEnglish = c.String(nullable: false, maxLength: 50), 16 | }) 17 | .PrimaryKey(t => t.Iso3); 18 | 19 | CreateTable( 20 | "dbo.Customers", 21 | c => new 22 | { 23 | CustomerID = c.Guid(nullable: false), 24 | CustomerName = c.String(nullable: false, maxLength: 128), 25 | CountryIso3 = c.String(nullable: false, maxLength: 3), 26 | RegionCode = c.String(maxLength: 3), 27 | }) 28 | .PrimaryKey(t => t.CustomerID) 29 | .ForeignKey("dbo.Countries", t => t.CountryIso3, cascadeDelete: true) 30 | .ForeignKey("dbo.Regions", t => t.RegionCode) 31 | .Index(t => t.CountryIso3) 32 | .Index(t => t.RegionCode); 33 | 34 | CreateTable( 35 | "dbo.Regions", 36 | c => new 37 | { 38 | RegionCode = c.String(nullable: false, maxLength: 3), 39 | Iso3 = c.String(nullable: false, maxLength: 3), 40 | RegionNameEnglish = c.String(nullable: false), 41 | }) 42 | .PrimaryKey(t => t.RegionCode) 43 | .ForeignKey("dbo.Countries", t => t.Iso3, cascadeDelete: true) 44 | .Index(t => t.Iso3); 45 | 46 | } 47 | 48 | public override void Down() 49 | { 50 | DropForeignKey("dbo.Customers", "RegionCode", "dbo.Regions"); 51 | DropForeignKey("dbo.Regions", "Iso3", "dbo.Countries"); 52 | DropForeignKey("dbo.Customers", "CountryIso3", "dbo.Countries"); 53 | DropIndex("dbo.Regions", new[] { "Iso3" }); 54 | DropIndex("dbo.Customers", new[] { "RegionCode" }); 55 | DropIndex("dbo.Customers", new[] { "CountryIso3" }); 56 | DropTable("dbo.Regions"); 57 | DropTable("dbo.Customers"); 58 | DropTable("dbo.Countries"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Blip.Data/Migrations/201709021326086_OrdersItems.cs: -------------------------------------------------------------------------------- 1 | namespace Blip.Data.Migrations 2 | { 3 | using System; 4 | using System.Data.Entity.Migrations; 5 | 6 | public partial class OrdersItems : DbMigration 7 | { 8 | public override void Up() 9 | { 10 | CreateTable( 11 | "dbo.Orders", 12 | c => new 13 | { 14 | OrderID = c.Guid(nullable: false), 15 | CustomerID = c.Guid(nullable: false), 16 | OrderDate = c.DateTime(nullable: false), 17 | Description = c.String(nullable: false, maxLength: 128), 18 | }) 19 | .PrimaryKey(t => t.OrderID) 20 | .ForeignKey("dbo.Customers", t => t.CustomerID, cascadeDelete: true) 21 | .Index(t => t.CustomerID); 22 | 23 | CreateTable( 24 | "dbo.Items", 25 | c => new 26 | { 27 | ItemID = c.Guid(nullable: false), 28 | Description = c.String(nullable: false, maxLength: 128), 29 | ReorderQuantity = c.Int(nullable: false), 30 | MSRP = c.Decimal(nullable: false, precision: 18, scale: 2), 31 | }) 32 | .PrimaryKey(t => t.ItemID); 33 | 34 | CreateTable( 35 | "dbo.OrderItems", 36 | c => new 37 | { 38 | ItemID = c.Guid(nullable: false), 39 | OrderID = c.Guid(nullable: false), 40 | Price = c.Decimal(nullable: false, precision: 18, scale: 2), 41 | Quantity = c.Short(nullable: false), 42 | }) 43 | .PrimaryKey(t => new { t.ItemID, t.OrderID }) 44 | .ForeignKey("dbo.Items", t => t.ItemID, cascadeDelete: true) 45 | .ForeignKey("dbo.Orders", t => t.OrderID, cascadeDelete: true) 46 | .Index(t => t.ItemID) 47 | .Index(t => t.OrderID); 48 | 49 | } 50 | 51 | public override void Down() 52 | { 53 | DropForeignKey("dbo.OrderItems", "OrderID", "dbo.Orders"); 54 | DropForeignKey("dbo.OrderItems", "ItemID", "dbo.Items"); 55 | DropForeignKey("dbo.Orders", "CustomerID", "dbo.Customers"); 56 | DropIndex("dbo.OrderItems", new[] { "OrderID" }); 57 | DropIndex("dbo.OrderItems", new[] { "ItemID" }); 58 | DropIndex("dbo.Orders", new[] { "CustomerID" }); 59 | DropTable("dbo.OrderItems"); 60 | DropTable("dbo.Items"); 61 | DropTable("dbo.Orders"); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Blip.Data/Orders/OrdersRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Blip.Entities.Orders.ViewModels; 5 | 6 | namespace Blip.Data.Orders 7 | { 8 | public class OrdersRepository 9 | { 10 | public CustomerOrdersListViewModel GetCustomerOrdersDisplay(Guid customerid) 11 | { 12 | if (customerid != null && customerid != Guid.Empty) 13 | { 14 | using (var context = new ApplicationDbContext()) 15 | { 16 | var customerRepo = new CustomersRepository(); 17 | var customer = customerRepo.GetCustomer(customerid); 18 | if (customer != null) 19 | { 20 | var customerOrdersListVm = new CustomerOrdersListViewModel() 21 | { 22 | CustomerID = customer.CustomerID, 23 | CustomerName = customer.CustomerName, 24 | CountryNameEnglish = context.Countries.Find(customer.CountryIso3).CountryNameEnglish, 25 | RegionNameEnglish = context.Regions.Find(customer.RegionCode).RegionNameEnglish 26 | }; 27 | 28 | List orderList = context.Orders.AsNoTracking() 29 | .Where(x => x.CustomerID == customerid) 30 | .OrderBy(x => x.OrderDate) 31 | .Select( x => 32 | new OrderDisplayViewModel 33 | { 34 | CustomerID = x.CustomerID, 35 | OrderID = x.OrderID, 36 | OrderDate = x.OrderDate, 37 | Description = x.Description 38 | }).ToList(); 39 | customerOrdersListVm.Orders = orderList; 40 | return customerOrdersListVm; 41 | } 42 | } 43 | } 44 | return null; 45 | } 46 | 47 | public void SaveOrders(List orders) 48 | { 49 | if (orders != null) 50 | { 51 | using (var context = new ApplicationDbContext()) 52 | { 53 | foreach (var order in orders) 54 | { 55 | var record = context.Orders.Find(order.OrderID); 56 | if (record != null) 57 | { 58 | record.Description = order.Description; 59 | } 60 | } 61 | context.SaveChanges(); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Blip.Data/App.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Blip.Web/Controllers/CustomerController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Web.Mvc; 3 | using Blip.Data; 4 | using Blip.Entities.Customers.ViewModels; 5 | 6 | namespace Blip.Web.Controllers 7 | { 8 | public class CustomerController : Controller 9 | { 10 | // GET: Customer 11 | public ActionResult Index() 12 | { 13 | var repo = new CustomersRepository(); 14 | var customerList = repo.GetCustomers(); 15 | return View(customerList); 16 | } 17 | 18 | [HttpGet] 19 | public ActionResult GetRegions(string iso3) 20 | { 21 | if (!string.IsNullOrWhiteSpace(iso3) && iso3.Length == 3) 22 | { 23 | var repo = new RegionsRepository(); 24 | 25 | IEnumerable regions = repo.GetRegions(iso3); 26 | return Json(regions, JsonRequestBehavior.AllowGet); 27 | } 28 | return null; 29 | } 30 | 31 | 32 | // GET: Customer/Details/5 33 | public ActionResult Details(int id) 34 | { 35 | return View(); 36 | } 37 | 38 | // GET: Customer/Create 39 | public ActionResult Create() 40 | { 41 | var repo = new CustomersRepository(); 42 | var customer = repo.CreateCustomer(); 43 | return View(customer); 44 | } 45 | 46 | // POST: Customer/Create 47 | [HttpPost] 48 | public ActionResult Create([Bind(Include = "CustomerID, CustomerName, SelectedCountryIso3, SelectedRegionCode")] CustomerEditViewModel model) 49 | { 50 | try 51 | { 52 | if (ModelState.IsValid) 53 | { 54 | var repo = new CustomersRepository(); 55 | bool saved = repo.SaveCustomer(model); 56 | if (saved) 57 | { 58 | return RedirectToAction("Index"); 59 | } 60 | } 61 | return View(); 62 | } 63 | catch 64 | { 65 | return View(); 66 | } 67 | } 68 | 69 | // GET: Customer/Edit/5 70 | public ActionResult Edit(int id) 71 | { 72 | return View(); 73 | } 74 | 75 | // POST: Customer/Edit/5 76 | [HttpPost] 77 | public ActionResult Edit(int id, FormCollection collection) 78 | { 79 | try 80 | { 81 | // TODO: Add update logic here 82 | 83 | return RedirectToAction("Index"); 84 | } 85 | catch 86 | { 87 | return View(); 88 | } 89 | } 90 | 91 | // GET: Customer/Delete/5 92 | public ActionResult Delete(int id) 93 | { 94 | return View(); 95 | } 96 | 97 | // POST: Customer/Delete/5 98 | [HttpPost] 99 | public ActionResult Delete(int id, FormCollection collection) 100 | { 101 | try 102 | { 103 | // TODO: Add delete logic here 104 | 105 | return RedirectToAction("Index"); 106 | } 107 | catch 108 | { 109 | return View(); 110 | } 111 | } 112 | } 113 | 114 | } -------------------------------------------------------------------------------- /Blip.Data/Customer/CustomersRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data.Entity; 4 | using System.Linq; 5 | using Blip.Entities.Customers; 6 | using Blip.Entities.Customers.ViewModels; 7 | 8 | namespace Blip.Data 9 | { 10 | public class CustomersRepository 11 | { 12 | public Customer GetCustomer(Guid customerid) 13 | { 14 | if (customerid != Guid.Empty) 15 | { 16 | using (var context = new ApplicationDbContext()) 17 | { 18 | var customer = context.Customers.AsNoTracking() 19 | .Where(x => x.CustomerID == customerid) 20 | .Single(); 21 | return customer; 22 | } 23 | } 24 | return null; 25 | } 26 | 27 | public List GetCustomers() 28 | { 29 | using (var context = new ApplicationDbContext()) 30 | { 31 | List customers = new List(); 32 | customers = context.Customers.AsNoTracking() 33 | .Include(x => x.Country) 34 | .Include(x => x.Region) 35 | .ToList(); 36 | 37 | if (customers != null) 38 | { 39 | List customersDisplay = new List(); 40 | foreach (var x in customers) 41 | { 42 | var customerDisplay = new CustomerDisplayViewModel() 43 | { 44 | CustomerID = x.CustomerID, 45 | CustomerName = x.CustomerName, 46 | CountryName = x.Country.CountryNameEnglish, 47 | RegionName = x.Region.RegionNameEnglish 48 | }; 49 | customersDisplay.Add(customerDisplay); 50 | } 51 | return customersDisplay; 52 | } 53 | return null; 54 | } 55 | } 56 | 57 | 58 | public CustomerEditViewModel CreateCustomer() 59 | { 60 | var cRepo = new CountriesRepository(); 61 | var rRepo = new RegionsRepository(); 62 | var customer = new CustomerEditViewModel() 63 | { 64 | CustomerID = Guid.NewGuid().ToString(), 65 | Countries = cRepo.GetCountries(), 66 | Regions = rRepo.GetRegions() 67 | }; 68 | return customer; 69 | } 70 | 71 | public bool SaveCustomer(CustomerEditViewModel customeredit) 72 | { 73 | if (customeredit != null) 74 | { 75 | using (var context = new ApplicationDbContext()) 76 | { 77 | if (Guid.TryParse(customeredit.CustomerID, out Guid newGuid)) 78 | { 79 | var customer = new Customer() 80 | { 81 | CustomerID = newGuid, 82 | CustomerName = customeredit.CustomerName, 83 | CountryIso3 = customeredit.SelectedCountryIso3, 84 | RegionCode = customeredit.SelectedRegionCode 85 | }; 86 | customer.Country = context.Countries.Find(customeredit.SelectedCountryIso3); 87 | customer.Region = context.Regions.Find(customeredit.SelectedRegionCode); 88 | 89 | context.Customers.Add(customer); 90 | context.SaveChanges(); 91 | return true; 92 | } 93 | } 94 | } 95 | // Return false if customeredit == null or CustomerID is not a guid 96 | return false; 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /Blip.Web/Views/Customer/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Blip.Entities.Customers.ViewModels.CustomerEditViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Customer"; 5 | } 6 |

Customer

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

Create a new customer by entering the customer name, country, and region.

15 |
16 |
17 | @Html.LabelFor(model => model.CustomerID, htmlAttributes: new { @class = "control-label col-md-2" }) 18 |
19 | @Html.EditorFor(model => model.CustomerID, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } }) 20 | @Html.ValidationMessageFor(model => model.CustomerID, "", new { @class = "text-danger" }) 21 |
22 |
23 |
24 | @Html.LabelFor(model => model.CustomerName, htmlAttributes: new { @class = "control-label col-md-2" }) 25 |
26 | @Html.EditorFor(model => model.CustomerName, new { htmlAttributes = new { @class = "form-control", @autofocus = "autofocus" } }) 27 | @Html.ValidationMessageFor(model => model.CustomerID, "", new { @class = "text-danger" }) 28 |
29 |
30 |
31 | @Html.LabelFor(x => Model.SelectedCountryIso3, htmlAttributes: new { @class = "control-label col-md-2" }) 32 |
33 | @Html.DropDownListFor(x => Model.SelectedCountryIso3, new SelectList(Model.Countries, "Value", "Text"), htmlAttributes: new { @class = "form-control", id = "Country" }) 34 | @Html.ValidationMessageFor(x => x.SelectedCountryIso3, "", new { @class = "text-danger" }) 35 |
36 |
37 |
38 | @Html.LabelFor(x => Model.SelectedRegionCode, htmlAttributes: new { @class = "control-label col-md-2" }) 39 |
40 | @Html.DropDownListFor(x => Model.SelectedRegionCode, new SelectList(Model.Regions, "Value", "Text"), htmlAttributes: new { @class = "form-control", @id = "Region" }) 41 | @Html.ValidationMessageFor(x => x.SelectedRegionCode, "", new { @class = "text-danger" }) 42 |
43 |
44 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 45 |
46 |
47 | 48 |
49 |
50 |
51 | } 52 | 53 |
54 | @Html.ActionLink("Back to List", "Index") 55 |
56 | 57 | @section Scripts { 58 | @Scripts.Render("~/bundles/jqueryval") 59 | 83 | } 84 | -------------------------------------------------------------------------------- /Blip.Web/Views/Order/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model Blip.Entities.Orders.ViewModels.CustomerOrdersListViewModel 2 | 3 | @{ 4 | ViewBag.Title = "Index"; 5 | } 6 | 7 |

Index

8 | 9 | @using (Html.BeginForm()) 10 | { 11 | @Html.AntiForgeryToken() 12 | 13 |
14 |
15 | @Html.LabelFor(model => model.CustomerID, new { @class = "control-label col-md-2" }) 16 |
17 | @Html.EditorFor(model => model.CustomerID, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } }) 18 |
19 |
20 |
21 | @Html.LabelFor(model => model.CustomerName, new { @class = "control-label col-md-2" }) 22 |
23 | @Html.EditorFor(model => model.CustomerName, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } }) 24 |
25 |
26 |
27 | @Html.LabelFor(model => model.CountryNameEnglish, new { @class = "control-label col-md-2" }) 28 |
29 | @Html.EditorFor(model => model.CountryNameEnglish, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } }) 30 |
31 |
32 |
33 | @Html.LabelFor(model => model.RegionNameEnglish, new { @class = "control-label col-md-2" }) 34 |
35 | @Html.EditorFor(model => model.RegionNameEnglish, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } }) 36 |
37 |
38 |
39 |
40 | 41 | 42 | 45 | 48 | 51 | 52 | @if (Model.Orders != null) 53 | { 54 | for (var i = 0; i < Model.Orders.Count(); i++) 55 | { 56 | 57 | @Html.HiddenFor(x => Model.Orders[i].CustomerID) 58 | 61 | 64 | 67 | 68 | } 69 | } 70 | @* 71 | 74 | 75 | 76 | *@ 77 |
43 | @Html.DisplayNameFor(model => model.Orders[0].OrderID) 44 | 46 | @Html.DisplayNameFor(model => model.Orders[0].OrderDate) 47 | 49 | @Html.DisplayNameFor(model => model.Orders[0].Description) 50 |
59 | @Html.TextBoxFor(x => Model.Orders[i].OrderID, new { @class = "form-control", @readonly = "readonly" }) 60 | 62 | @Html.TextBoxFor(x => Model.Orders[i].OrderDate, new { @class = "form-control", @readonly = "readonly" }) 63 | 65 | @Html.TextBoxFor(x => Model.Orders[i].Description, new { @class = "form-control" }) 66 |
72 | @Html.ActionLink("Add", "Edit", new { customerid = Model.CustomerID, orderid = Model.OrderID }, htmlAttributes: new { @class = "btn btn-success" }) 73 |
78 |
79 |
80 |
81 |
82 | 83 |
84 |
85 |
86 | } 87 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # BlipBinding 2 | 3 | **_BlipBinding_** is an ASP.NET MVC case study solution created to accompany a guide in the [**PluralSight Guides**](https://www.pluralsight.com/guides) collection for Microsoft .NET technologies. 4 | 5 | ## PluralSight Guides 6 | 7 | [ASP.NET MVC - Getting default data binding right for hierarchical views](https://www.pluralsight.com/guides/asp-net-mvc-getting-default-data-binding-right-for-hierarchical-views) - The power of default model binding in ASP.NET MVC extends beyond the flat data model of a simple input form or list of records. Using a few straightforward coding techniques, developers can use ASP.NET to create forms and collect data for hierarchical entity relationships. This guide presents an example of using ASP.NET MVC model binding to present and collect hierarchical form data in a hierarchical structure. 8 | 9 | *Notice: PluralSight and the author(s) disclaim any liability for errors or omissions in this code. See the [Disclaimer of Warranties and Limitation of Liability](#disclaimer-of-warranties-and-limitation-of-liability) for complete information.* 10 | 11 | ## Design Patterns 12 | 13 | Model-View-ViewModel 14 | Repository 15 | 16 | ## Solution Projects 17 | 18 | | Project | Application Layer | 19 | | :--- | :--- | 20 | | Blip.Data | Data Context and Repositories | 21 | | Blip.Entities | Data Entities | 22 | | Blip.Web | User Interface (views) and Business Logic (controllers) | 23 | 24 | ## Technologies 25 | 26 | | Dependency | Version* 27 | | :--- | ---: 28 | | .NET Framework | 4.6.2 29 | | ASP.NET MVC | 5.2.3 30 | | Bootstrap | 3.3.7 31 | | C# | 6 32 | | Entity Framework | 6.1.3 33 | | jQuery | 3.2.1 34 | | jQuery Validation | 1.16.0 35 | | Microsoft Identity | 2.2.1 36 | | Microsoft jQuery Unobtrusive Validation | 3.2.3 37 | 38 | * As of the latest commit. 39 | 40 | ## Getting Started 41 | 42 | 1. Download or clone this repository. 43 | 1. Open the solution in Visual Studio 2017 or higher. 44 | 1. Select the **Blip.Data** project. 45 | 1. Open a Package Manager Console window. 46 | 1. Select "Blip.Data" for **Default Project**. 47 | 1. Run: `update-database`. 48 | 49 | This will create the database, apply Entity Framework migrations, and run the `Seed` method to populate the database with values for the lookup tables. 50 | 51 | ## Configuration 52 | 53 | * Two projects contain configuration strings which may require modification for the developer's specific environment: 54 | 55 | | Project | File 56 | | :--- | :--- 57 | | Blip.Data | App.config 58 | | Blip.Web | Web.config 59 | 60 | * The configuration strings specify the instance of SQL Server Express installed with Visual Studio 2017 as the target database server: `Data Source=(localdb)\ProjectsV13`. Developers using a different target database will have to change the connection strings in both projects. 61 | 62 | ## License 63 | 64 | This project is licensed under the terms of the MIT license. 65 | 66 | ## Contributing 67 | 68 | See the accompanying instructions on [How to contribute](CONTRIBUTING.md). 69 | 70 | ## Disclaimer of Warranties and Limitation of Liability 71 | 72 | The contents of this repository are offered on an as-is and as-available basis and the authors make no representations or warranties of any kind concerning the contents, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. 73 | 74 | To the extent possible, in no event will the authors be liable on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of the use of the contents, even if the the authors have been advised of the possibility of such losses, costs, expenses, or damages. 75 | 76 | The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. -------------------------------------------------------------------------------- /Blip.Web/Scripts/respond.min.js: -------------------------------------------------------------------------------- 1 | /*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl 2 | * Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT 3 | * */ 4 | 5 | !function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b #mq-test-1 { width: 42px; }',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";if(a.matchMedia&&a.matchMedia("all").addListener)return!1;var b=a.matchMedia,c=b("only all").matches,d=!1,e=0,f=[],g=function(){a.clearTimeout(e),e=a.setTimeout(function(){for(var c=0,d=f.length;d>c;c++){var e=f[c].mql,g=f[c].listeners||[],h=b(e.media).matches;if(h!==e.matches){e.matches=h;for(var i=0,j=g.length;j>i;i++)g[i].call(a,e)}}},30)};a.matchMedia=function(e){var h=b(e),i=[],j=0;return h.addListener=function(b){c&&(d||(d=!0,a.addEventListener("resize",g,!0)),0===j&&(j=f.push({mql:h,listeners:i})),i.push(b))},h.removeListener=function(a){for(var b=0,c=i.length;c>b;b++)i[b]===a&&i.splice(b,1)},h}}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b 2 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /Blip.Web/Scripts/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /* 16 | ** Unobtrusive validation support library for jQuery and jQuery Validate 17 | ** Copyright (C) Microsoft Corporation. All rights reserved. 18 | */ 19 | (function(a){var d=a.validator,b,e="unobtrusiveValidation";function c(a,b,c){a.rules[b]=c;if(a.message)a.messages[b]=a.message}function j(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function f(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function h(a){return a.substr(0,a.lastIndexOf(".")+1)}function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);return a}function m(c,e){var b=a(this).find("[data-valmsg-for='"+f(e[0].name)+"']"),d=b.attr("data-valmsg-replace"),g=d?a.parseJSON(d)!==false:null;b.removeClass("field-validation-valid").addClass("field-validation-error");c.data("unobtrusiveContainer",b);if(g){b.empty();c.removeClass("input-validation-error").appendTo(b)}else c.hide()}function l(e,d){var c=a(this).find("[data-valmsg-summary=true]"),b=c.find("ul");if(b&&b.length&&d.errorList.length){b.empty();c.addClass("validation-summary-errors").removeClass("validation-summary-valid");a.each(d.errorList,function(){a("
  • ").html(this.message).appendTo(b)})}}function k(d){var b=d.data("unobtrusiveContainer"),c=b.attr("data-valmsg-replace"),e=c?a.parseJSON(c):null;if(b){b.addClass("field-validation-valid").removeClass("field-validation-error");d.removeData("unobtrusiveContainer");e&&b.empty()}}function n(){var b=a(this),c="__jquery_unobtrusive_validation_form_reset";if(b.data(c))return;b.data(c,true);try{b.data("validator").resetForm()}finally{b.removeData(c)}b.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors");b.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}function i(b){var c=a(b),f=c.data(e),i=a.proxy(n,b),g=d.unobtrusive.options||{},h=function(e,d){var c=g[e];c&&a.isFunction(c)&&c.apply(b,d)};if(!f){f={options:{errorClass:g.errorClass||"input-validation-error",errorElement:g.errorElement||"span",errorPlacement:function(){m.apply(b,arguments);h("errorPlacement",arguments)},invalidHandler:function(){l.apply(b,arguments);h("invalidHandler",arguments)},messages:{},rules:{},success:function(){k.apply(b,arguments);h("success",arguments)}},attachValidation:function(){c.off("reset."+e,i).on("reset."+e,i).validate(this.options)},validate:function(){c.validate();return c.valid()}};c.data(e,f)}return f}d.unobtrusive={adapters:[],parseElement:function(b,h){var d=a(b),f=d.parents("form")[0],c,e,g;if(!f)return;c=i(f);c.options.rules[b.name]=e={};c.options.messages[b.name]=g={};a.each(this.adapters,function(){var c="data-val-"+this.name,i=d.attr(c),h={};if(i!==undefined){c+="-";a.each(this.params,function(){h[this]=d.attr(c+this)});this.adapt({element:b,form:f,message:i,params:h,rules:e,messages:g})}});a.extend(e,{__dummy__:true});!h&&c.attachValidation()},parse:function(c){var b=a(c),e=b.parents().addBack().filter("form").add(b.find("form")).has("[data-val=true]");b.find("[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});e.each(function(){var a=i(this);a&&a.attachValidation()})}};b=d.unobtrusive.adapters;b.add=function(c,a,b){if(!b){b=a;a=[]}this.push({name:c,params:a,adapt:b});return this};b.addBool=function(a,b){return this.add(a,function(d){c(d,b||a,true)})};b.addMinMax=function(e,g,f,a,d,b){return this.add(e,[d||"min",b||"max"],function(b){var e=b.params.min,d=b.params.max;if(e&&d)c(b,a,[e,d]);else if(e)c(b,g,e);else d&&c(b,f,d)})};b.addSingleVal=function(a,b,d){return this.add(a,[b||"val"],function(e){c(e,d||a,e.params[b])})};d.addMethod("__dummy__",function(){return true});d.addMethod("regex",function(b,c,d){var a;if(this.optional(c))return true;a=(new RegExp(d)).exec(b);return a&&a.index===0&&a[0].length===b.length});d.addMethod("nonalphamin",function(c,d,b){var a;if(b){a=c.match(/\W/g);a=a&&a.length>=b}return a});if(d.methods.extension){b.addSingleVal("accept","mimtype");b.addSingleVal("extension","extension")}else b.addSingleVal("extension","extension","accept");b.addSingleVal("regex","pattern");b.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");b.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range");b.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength");b.add("equalto",["other"],function(b){var i=h(b.element.name),j=b.params.other,d=g(j,i),e=a(b.form).find(":input").filter("[name='"+f(d)+"']")[0];c(b,"equalTo",e)});b.add("required",function(a){(a.element.tagName.toUpperCase()!=="INPUT"||a.element.type.toUpperCase()!=="CHECKBOX")&&c(a,"required",true)});b.add("remote",["url","type","additionalfields"],function(b){var d={url:b.params.url,type:b.params.type||"GET",data:{}},e=h(b.element.name);a.each(j(b.params.additionalfields||b.element.name),function(i,h){var c=g(h,e);d.data[c]=function(){var d=a(b.form).find(":input").filter("[name='"+f(c)+"']");return d.is(":checkbox")?d.filter(":checked").val()||d.filter(":hidden").val()||"":d.is(":radio")?d.filter(":checked").val()||"":d.val()}});c(b,"remote",d)});b.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&c(a,"minlength",a.params.min);a.params.nonalphamin&&c(a,"nonalphamin",a.params.nonalphamin);a.params.regex&&c(a,"regex",a.params.regex)});a(function(){d.unobtrusive.parse(document)})})(jQuery); -------------------------------------------------------------------------------- /Blip.Common/Blip.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | 9 | 10 | 2.0 11 | {7BC8455D-5B90-4A20-AED3-D988781494F4} 12 | {fae04ec0-301f-11d3-bf4b-00c04f79efbc} 13 | Library 14 | Properties 15 | Blip.Common 16 | Blip.Common 17 | v4.6.2 18 | true 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | true 30 | full 31 | false 32 | bin\ 33 | DEBUG;TRACE 34 | prompt 35 | 4 36 | 37 | 38 | true 39 | pdbonly 40 | true 41 | bin\ 42 | TRACE 43 | prompt 44 | 4 45 | 46 | 47 | 48 | ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.7\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | App.config 72 | 73 | 74 | App.config 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 10.0 89 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 98 | 99 | 100 | 101 | 102 | 109 | -------------------------------------------------------------------------------- /Blip.Web/ApplicationInsights.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | search|spider|crawl|Bot|Monitor|AlwaysOn 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | core.windows.net 32 | core.chinacloudapi.cn 33 | core.cloudapi.de 34 | core.usgovcloudapi.net 35 | localhost 36 | 127.0.0.1 37 | 38 | 39 | 40 | 57 | 58 | 59 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | 72 | System.Web.Handlers.TransferRequestHandler 73 | Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.RequestDataHttpHandler 74 | System.Web.StaticFileHandler 75 | System.Web.Handlers.AssemblyResourceLoader 76 | System.Web.Optimization.BundleHandler 77 | System.Web.Script.Services.ScriptHandlerFactory 78 | System.Web.Handlers.TraceHandler 79 | System.Web.Services.Discovery.DiscoveryRequestHandler 80 | System.Web.HttpDebugHandler 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 5 91 | Event 92 | 93 | 94 | 5 95 | Event 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Blip.Data/Migrations/201708222251192_InitialMigration.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 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 122 | 123 | 124 | dbo 125 | 126 | -------------------------------------------------------------------------------- /Blip.Entities/Blip.Entities.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | 9 | 10 | 2.0 11 | {3A1FF2CA-E0AA-4E04-A082-B8FCCD23F8F0} 12 | {fae04ec0-301f-11d3-bf4b-00c04f79efbc} 13 | Library 14 | Properties 15 | Blip.Entities 16 | Blip.Entities 17 | v4.6.2 18 | true 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | true 30 | full 31 | false 32 | bin\ 33 | DEBUG;TRACE 34 | prompt 35 | 4 36 | 37 | 38 | true 39 | pdbonly 40 | true 41 | bin\ 42 | TRACE 43 | prompt 44 | 4 45 | 46 | 47 | 48 | ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.7\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll 49 | 50 | 51 | 52 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 53 | True 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll 66 | 67 | 68 | ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll 69 | 70 | 71 | ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll 72 | 73 | 74 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll 75 | 76 | 77 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll 78 | 79 | 80 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | App.config 94 | 95 | 96 | App.config 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 10.0 118 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 127 | 128 | 129 | 130 | 131 | 138 | -------------------------------------------------------------------------------- /Blip.Web/Scripts/respond.js: -------------------------------------------------------------------------------- 1 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 2 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 3 | (function(w) { 4 | "use strict"; 5 | w.matchMedia = w.matchMedia || function(doc, undefined) { 6 | var bool, docElem = doc.documentElement, refNode = docElem.firstElementChild || docElem.firstChild, fakeBody = doc.createElement("body"), div = doc.createElement("div"); 7 | div.id = "mq-test-1"; 8 | div.style.cssText = "position:absolute;top:-100em"; 9 | fakeBody.style.background = "none"; 10 | fakeBody.appendChild(div); 11 | return function(q) { 12 | div.innerHTML = '­'; 13 | docElem.insertBefore(fakeBody, refNode); 14 | bool = div.offsetWidth === 42; 15 | docElem.removeChild(fakeBody); 16 | return { 17 | matches: bool, 18 | media: q 19 | }; 20 | }; 21 | }(w.document); 22 | })(this); 23 | 24 | /*! Respond.js v1.4.0: min/max-width media query polyfill. (c) Scott Jehl. MIT Lic. j.mp/respondjs */ 25 | (function(w) { 26 | "use strict"; 27 | var respond = {}; 28 | w.respond = respond; 29 | respond.update = function() {}; 30 | var requestQueue = [], xmlHttp = function() { 31 | var xmlhttpmethod = false; 32 | try { 33 | xmlhttpmethod = new w.XMLHttpRequest(); 34 | } catch (e) { 35 | xmlhttpmethod = new w.ActiveXObject("Microsoft.XMLHTTP"); 36 | } 37 | return function() { 38 | return xmlhttpmethod; 39 | }; 40 | }(), ajax = function(url, callback) { 41 | var req = xmlHttp(); 42 | if (!req) { 43 | return; 44 | } 45 | req.open("GET", url, true); 46 | req.onreadystatechange = function() { 47 | if (req.readyState !== 4 || req.status !== 200 && req.status !== 304) { 48 | return; 49 | } 50 | callback(req.responseText); 51 | }; 52 | if (req.readyState === 4) { 53 | return; 54 | } 55 | req.send(null); 56 | }; 57 | respond.ajax = ajax; 58 | respond.queue = requestQueue; 59 | respond.regex = { 60 | media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi, 61 | keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi, 62 | urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, 63 | findStyles: /@media *([^\{]+)\{([\S\s]+?)$/, 64 | only: /(only\s+)?([a-zA-Z]+)\s?/, 65 | minw: /\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/, 66 | maxw: /\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ 67 | }; 68 | respond.mediaQueriesSupported = w.matchMedia && w.matchMedia("only all") !== null && w.matchMedia("only all").matches; 69 | if (respond.mediaQueriesSupported) { 70 | return; 71 | } 72 | var doc = w.document, docElem = doc.documentElement, mediastyles = [], rules = [], appendedEls = [], parsedSheets = {}, resizeThrottle = 30, head = doc.getElementsByTagName("head")[0] || docElem, base = doc.getElementsByTagName("base")[0], links = head.getElementsByTagName("link"), lastCall, resizeDefer, eminpx, getEmValue = function() { 73 | var ret, div = doc.createElement("div"), body = doc.body, originalHTMLFontSize = docElem.style.fontSize, originalBodyFontSize = body && body.style.fontSize, fakeUsed = false; 74 | div.style.cssText = "position:absolute;font-size:1em;width:1em"; 75 | if (!body) { 76 | body = fakeUsed = doc.createElement("body"); 77 | body.style.background = "none"; 78 | } 79 | docElem.style.fontSize = "100%"; 80 | body.style.fontSize = "100%"; 81 | body.appendChild(div); 82 | if (fakeUsed) { 83 | docElem.insertBefore(body, docElem.firstChild); 84 | } 85 | ret = div.offsetWidth; 86 | if (fakeUsed) { 87 | docElem.removeChild(body); 88 | } else { 89 | body.removeChild(div); 90 | } 91 | docElem.style.fontSize = originalHTMLFontSize; 92 | if (originalBodyFontSize) { 93 | body.style.fontSize = originalBodyFontSize; 94 | } 95 | ret = eminpx = parseFloat(ret); 96 | return ret; 97 | }, applyMedia = function(fromResize) { 98 | var name = "clientWidth", docElemProp = docElem[name], currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime(); 99 | if (fromResize && lastCall && now - lastCall < resizeThrottle) { 100 | w.clearTimeout(resizeDefer); 101 | resizeDefer = w.setTimeout(applyMedia, resizeThrottle); 102 | return; 103 | } else { 104 | lastCall = now; 105 | } 106 | for (var i in mediastyles) { 107 | if (mediastyles.hasOwnProperty(i)) { 108 | var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = "em"; 109 | if (!!min) { 110 | min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1); 111 | } 112 | if (!!max) { 113 | max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1); 114 | } 115 | if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) { 116 | if (!styleBlocks[thisstyle.media]) { 117 | styleBlocks[thisstyle.media] = []; 118 | } 119 | styleBlocks[thisstyle.media].push(rules[thisstyle.rules]); 120 | } 121 | } 122 | } 123 | for (var j in appendedEls) { 124 | if (appendedEls.hasOwnProperty(j)) { 125 | if (appendedEls[j] && appendedEls[j].parentNode === head) { 126 | head.removeChild(appendedEls[j]); 127 | } 128 | } 129 | } 130 | appendedEls.length = 0; 131 | for (var k in styleBlocks) { 132 | if (styleBlocks.hasOwnProperty(k)) { 133 | var ss = doc.createElement("style"), css = styleBlocks[k].join("\n"); 134 | ss.type = "text/css"; 135 | ss.media = k; 136 | head.insertBefore(ss, lastLink.nextSibling); 137 | if (ss.styleSheet) { 138 | ss.styleSheet.cssText = css; 139 | } else { 140 | ss.appendChild(doc.createTextNode(css)); 141 | } 142 | appendedEls.push(ss); 143 | } 144 | } 145 | }, translate = function(styles, href, media) { 146 | var qs = styles.replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0; 147 | href = href.substring(0, href.lastIndexOf("/")); 148 | var repUrls = function(css) { 149 | return css.replace(respond.regex.urls, "$1" + href + "$2$3"); 150 | }, useMedia = !ql && media; 151 | if (href.length) { 152 | href += "/"; 153 | } 154 | if (useMedia) { 155 | ql = 1; 156 | } 157 | for (var i = 0; i < ql; i++) { 158 | var fullq, thisq, eachq, eql; 159 | if (useMedia) { 160 | fullq = media; 161 | rules.push(repUrls(styles)); 162 | } else { 163 | fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1; 164 | rules.push(RegExp.$2 && repUrls(RegExp.$2)); 165 | } 166 | eachq = fullq.split(","); 167 | eql = eachq.length; 168 | for (var j = 0; j < eql; j++) { 169 | thisq = eachq[j]; 170 | mediastyles.push({ 171 | media: thisq.split("(")[0].match(respond.regex.only) && RegExp.$2 || "all", 172 | rules: rules.length - 1, 173 | hasquery: thisq.indexOf("(") > -1, 174 | minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || ""), 175 | maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || "") 176 | }); 177 | } 178 | } 179 | applyMedia(); 180 | }, makeRequests = function() { 181 | if (requestQueue.length) { 182 | var thisRequest = requestQueue.shift(); 183 | ajax(thisRequest.href, function(styles) { 184 | translate(styles, thisRequest.href, thisRequest.media); 185 | parsedSheets[thisRequest.href] = true; 186 | w.setTimeout(function() { 187 | makeRequests(); 188 | }, 0); 189 | }); 190 | } 191 | }, ripCSS = function() { 192 | for (var i = 0; i < links.length; i++) { 193 | var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet"; 194 | if (!!href && isCSS && !parsedSheets[href]) { 195 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) { 196 | translate(sheet.styleSheet.rawCssText, href, media); 197 | parsedSheets[href] = true; 198 | } else { 199 | if (!/^([a-zA-Z:]*\/\/)/.test(href) && !base || href.replace(RegExp.$1, "").split("/")[0] === w.location.host) { 200 | if (href.substring(0, 2) === "//") { 201 | href = w.location.protocol + href; 202 | } 203 | requestQueue.push({ 204 | href: href, 205 | media: media 206 | }); 207 | } 208 | } 209 | } 210 | } 211 | makeRequests(); 212 | }; 213 | ripCSS(); 214 | respond.update = ripCSS; 215 | respond.getEmValue = getEmValue; 216 | function callMedia() { 217 | applyMedia(true); 218 | } 219 | if (w.addEventListener) { 220 | w.addEventListener("resize", callMedia, false); 221 | } else if (w.attachEvent) { 222 | w.attachEvent("onresize", callMedia); 223 | } 224 | })(this); -------------------------------------------------------------------------------- /Blip.Data/Migrations/201709021326086_OrdersItems.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 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 122 | 123 | 124 | dbo 125 | 126 | -------------------------------------------------------------------------------- /Blip.Data/Blip.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | 9 | 10 | 2.0 11 | {C8F46FA8-BEF3-4592-BD57-E5E9ECFCA1B9} 12 | {fae04ec0-301f-11d3-bf4b-00c04f79efbc} 13 | Library 14 | Properties 15 | Blip.Data 16 | Blip.Data 17 | v4.6.2 18 | true 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | true 30 | full 31 | false 32 | bin\ 33 | DEBUG;TRACE 34 | prompt 35 | 4 36 | 37 | 38 | true 39 | pdbonly 40 | true 41 | bin\ 42 | TRACE 43 | prompt 44 | 4 45 | 46 | 47 | 48 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll 49 | 50 | 51 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll 52 | 53 | 54 | ..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll 55 | 56 | 57 | ..\packages\Microsoft.AspNet.Identity.EntityFramework.2.2.1\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll 58 | 59 | 60 | ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.7\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll 61 | 62 | 63 | 64 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 65 | True 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll 78 | 79 | 80 | ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll 81 | 82 | 83 | ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll 84 | 85 | 86 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll 87 | 88 | 89 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll 90 | 91 | 92 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | App.config 106 | 107 | 108 | App.config 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 201708222251192_InitialMigration.cs 122 | 123 | 124 | 125 | 201709021326086_OrdersItems.cs 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | {3a1ff2ca-e0aa-4e04-a082-b8fccd23f8f0} 137 | Blip.Entities 138 | 139 | 140 | 141 | 142 | 201708222251192_InitialMigration.cs 143 | 144 | 145 | 201709021326086_OrdersItems.cs 146 | 147 | 148 | 149 | 10.0 150 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 159 | 160 | 161 | 162 | 163 | 170 | -------------------------------------------------------------------------------- /Blip.Web/Scripts/respond.matchmedia.addListener.js: -------------------------------------------------------------------------------- 1 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 2 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 3 | (function(w) { 4 | "use strict"; 5 | w.matchMedia = w.matchMedia || function(doc, undefined) { 6 | var bool, docElem = doc.documentElement, refNode = docElem.firstElementChild || docElem.firstChild, fakeBody = doc.createElement("body"), div = doc.createElement("div"); 7 | div.id = "mq-test-1"; 8 | div.style.cssText = "position:absolute;top:-100em"; 9 | fakeBody.style.background = "none"; 10 | fakeBody.appendChild(div); 11 | return function(q) { 12 | div.innerHTML = '­'; 13 | docElem.insertBefore(fakeBody, refNode); 14 | bool = div.offsetWidth === 42; 15 | docElem.removeChild(fakeBody); 16 | return { 17 | matches: bool, 18 | media: q 19 | }; 20 | }; 21 | }(w.document); 22 | })(this); 23 | 24 | /*! matchMedia() polyfill addListener/removeListener extension. Author & copyright (c) 2012: Scott Jehl. Dual MIT/BSD license */ 25 | (function(w) { 26 | "use strict"; 27 | if (w.matchMedia && w.matchMedia("all").addListener) { 28 | return false; 29 | } 30 | var localMatchMedia = w.matchMedia, hasMediaQueries = localMatchMedia("only all").matches, isListening = false, timeoutID = 0, queries = [], handleChange = function(evt) { 31 | w.clearTimeout(timeoutID); 32 | timeoutID = w.setTimeout(function() { 33 | for (var i = 0, il = queries.length; i < il; i++) { 34 | var mql = queries[i].mql, listeners = queries[i].listeners || [], matches = localMatchMedia(mql.media).matches; 35 | if (matches !== mql.matches) { 36 | mql.matches = matches; 37 | for (var j = 0, jl = listeners.length; j < jl; j++) { 38 | listeners[j].call(w, mql); 39 | } 40 | } 41 | } 42 | }, 30); 43 | }; 44 | w.matchMedia = function(media) { 45 | var mql = localMatchMedia(media), listeners = [], index = 0; 46 | mql.addListener = function(listener) { 47 | if (!hasMediaQueries) { 48 | return; 49 | } 50 | if (!isListening) { 51 | isListening = true; 52 | w.addEventListener("resize", handleChange, true); 53 | } 54 | if (index === 0) { 55 | index = queries.push({ 56 | mql: mql, 57 | listeners: listeners 58 | }); 59 | } 60 | listeners.push(listener); 61 | }; 62 | mql.removeListener = function(listener) { 63 | for (var i = 0, il = listeners.length; i < il; i++) { 64 | if (listeners[i] === listener) { 65 | listeners.splice(i, 1); 66 | } 67 | } 68 | }; 69 | return mql; 70 | }; 71 | })(this); 72 | 73 | /*! Respond.js v1.4.0: min/max-width media query polyfill. (c) Scott Jehl. MIT Lic. j.mp/respondjs */ 74 | (function(w) { 75 | "use strict"; 76 | var respond = {}; 77 | w.respond = respond; 78 | respond.update = function() {}; 79 | var requestQueue = [], xmlHttp = function() { 80 | var xmlhttpmethod = false; 81 | try { 82 | xmlhttpmethod = new w.XMLHttpRequest(); 83 | } catch (e) { 84 | xmlhttpmethod = new w.ActiveXObject("Microsoft.XMLHTTP"); 85 | } 86 | return function() { 87 | return xmlhttpmethod; 88 | }; 89 | }(), ajax = function(url, callback) { 90 | var req = xmlHttp(); 91 | if (!req) { 92 | return; 93 | } 94 | req.open("GET", url, true); 95 | req.onreadystatechange = function() { 96 | if (req.readyState !== 4 || req.status !== 200 && req.status !== 304) { 97 | return; 98 | } 99 | callback(req.responseText); 100 | }; 101 | if (req.readyState === 4) { 102 | return; 103 | } 104 | req.send(null); 105 | }; 106 | respond.ajax = ajax; 107 | respond.queue = requestQueue; 108 | respond.regex = { 109 | media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi, 110 | keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi, 111 | urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, 112 | findStyles: /@media *([^\{]+)\{([\S\s]+?)$/, 113 | only: /(only\s+)?([a-zA-Z]+)\s?/, 114 | minw: /\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/, 115 | maxw: /\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ 116 | }; 117 | respond.mediaQueriesSupported = w.matchMedia && w.matchMedia("only all") !== null && w.matchMedia("only all").matches; 118 | if (respond.mediaQueriesSupported) { 119 | return; 120 | } 121 | var doc = w.document, docElem = doc.documentElement, mediastyles = [], rules = [], appendedEls = [], parsedSheets = {}, resizeThrottle = 30, head = doc.getElementsByTagName("head")[0] || docElem, base = doc.getElementsByTagName("base")[0], links = head.getElementsByTagName("link"), lastCall, resizeDefer, eminpx, getEmValue = function() { 122 | var ret, div = doc.createElement("div"), body = doc.body, originalHTMLFontSize = docElem.style.fontSize, originalBodyFontSize = body && body.style.fontSize, fakeUsed = false; 123 | div.style.cssText = "position:absolute;font-size:1em;width:1em"; 124 | if (!body) { 125 | body = fakeUsed = doc.createElement("body"); 126 | body.style.background = "none"; 127 | } 128 | docElem.style.fontSize = "100%"; 129 | body.style.fontSize = "100%"; 130 | body.appendChild(div); 131 | if (fakeUsed) { 132 | docElem.insertBefore(body, docElem.firstChild); 133 | } 134 | ret = div.offsetWidth; 135 | if (fakeUsed) { 136 | docElem.removeChild(body); 137 | } else { 138 | body.removeChild(div); 139 | } 140 | docElem.style.fontSize = originalHTMLFontSize; 141 | if (originalBodyFontSize) { 142 | body.style.fontSize = originalBodyFontSize; 143 | } 144 | ret = eminpx = parseFloat(ret); 145 | return ret; 146 | }, applyMedia = function(fromResize) { 147 | var name = "clientWidth", docElemProp = docElem[name], currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime(); 148 | if (fromResize && lastCall && now - lastCall < resizeThrottle) { 149 | w.clearTimeout(resizeDefer); 150 | resizeDefer = w.setTimeout(applyMedia, resizeThrottle); 151 | return; 152 | } else { 153 | lastCall = now; 154 | } 155 | for (var i in mediastyles) { 156 | if (mediastyles.hasOwnProperty(i)) { 157 | var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = "em"; 158 | if (!!min) { 159 | min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1); 160 | } 161 | if (!!max) { 162 | max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1); 163 | } 164 | if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) { 165 | if (!styleBlocks[thisstyle.media]) { 166 | styleBlocks[thisstyle.media] = []; 167 | } 168 | styleBlocks[thisstyle.media].push(rules[thisstyle.rules]); 169 | } 170 | } 171 | } 172 | for (var j in appendedEls) { 173 | if (appendedEls.hasOwnProperty(j)) { 174 | if (appendedEls[j] && appendedEls[j].parentNode === head) { 175 | head.removeChild(appendedEls[j]); 176 | } 177 | } 178 | } 179 | appendedEls.length = 0; 180 | for (var k in styleBlocks) { 181 | if (styleBlocks.hasOwnProperty(k)) { 182 | var ss = doc.createElement("style"), css = styleBlocks[k].join("\n"); 183 | ss.type = "text/css"; 184 | ss.media = k; 185 | head.insertBefore(ss, lastLink.nextSibling); 186 | if (ss.styleSheet) { 187 | ss.styleSheet.cssText = css; 188 | } else { 189 | ss.appendChild(doc.createTextNode(css)); 190 | } 191 | appendedEls.push(ss); 192 | } 193 | } 194 | }, translate = function(styles, href, media) { 195 | var qs = styles.replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0; 196 | href = href.substring(0, href.lastIndexOf("/")); 197 | var repUrls = function(css) { 198 | return css.replace(respond.regex.urls, "$1" + href + "$2$3"); 199 | }, useMedia = !ql && media; 200 | if (href.length) { 201 | href += "/"; 202 | } 203 | if (useMedia) { 204 | ql = 1; 205 | } 206 | for (var i = 0; i < ql; i++) { 207 | var fullq, thisq, eachq, eql; 208 | if (useMedia) { 209 | fullq = media; 210 | rules.push(repUrls(styles)); 211 | } else { 212 | fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1; 213 | rules.push(RegExp.$2 && repUrls(RegExp.$2)); 214 | } 215 | eachq = fullq.split(","); 216 | eql = eachq.length; 217 | for (var j = 0; j < eql; j++) { 218 | thisq = eachq[j]; 219 | mediastyles.push({ 220 | media: thisq.split("(")[0].match(respond.regex.only) && RegExp.$2 || "all", 221 | rules: rules.length - 1, 222 | hasquery: thisq.indexOf("(") > -1, 223 | minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || ""), 224 | maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || "") 225 | }); 226 | } 227 | } 228 | applyMedia(); 229 | }, makeRequests = function() { 230 | if (requestQueue.length) { 231 | var thisRequest = requestQueue.shift(); 232 | ajax(thisRequest.href, function(styles) { 233 | translate(styles, thisRequest.href, thisRequest.media); 234 | parsedSheets[thisRequest.href] = true; 235 | w.setTimeout(function() { 236 | makeRequests(); 237 | }, 0); 238 | }); 239 | } 240 | }, ripCSS = function() { 241 | for (var i = 0; i < links.length; i++) { 242 | var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet"; 243 | if (!!href && isCSS && !parsedSheets[href]) { 244 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) { 245 | translate(sheet.styleSheet.rawCssText, href, media); 246 | parsedSheets[href] = true; 247 | } else { 248 | if (!/^([a-zA-Z:]*\/\/)/.test(href) && !base || href.replace(RegExp.$1, "").split("/")[0] === w.location.host) { 249 | if (href.substring(0, 2) === "//") { 250 | href = w.location.protocol + href; 251 | } 252 | requestQueue.push({ 253 | href: href, 254 | media: media 255 | }); 256 | } 257 | } 258 | } 259 | } 260 | makeRequests(); 261 | }; 262 | ripCSS(); 263 | respond.update = ripCSS; 264 | respond.getEmValue = getEmValue; 265 | function callMedia() { 266 | applyMedia(true); 267 | } 268 | if (w.addEventListener) { 269 | w.addEventListener("resize", callMedia, false); 270 | } else if (w.attachEvent) { 271 | w.attachEvent("onresize", callMedia); 272 | } 273 | })(this); -------------------------------------------------------------------------------- /Blip.Web/Blip.Web.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Debug 8 | AnyCPU 9 | 10 | 11 | 2.0 12 | {C822CC2D-7129-46F8-9CA0-A519046EB5A7} 13 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 14 | Library 15 | Properties 16 | BlipProjects 17 | BlipProjects 18 | v4.6.2 19 | false 20 | true 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | true 32 | full 33 | false 34 | bin\ 35 | DEBUG;TRACE 36 | prompt 37 | 4 38 | 39 | 40 | true 41 | pdbonly 42 | true 43 | bin\ 44 | TRACE 45 | prompt 46 | 4 47 | 48 | 49 | 50 | ..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll 51 | 52 | 53 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll 54 | 55 | 56 | ..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll 57 | 58 | 59 | ..\packages\Microsoft.ApplicationInsights.Agent.Intercept.2.4.0\lib\net45\Microsoft.AI.Agent.Intercept.dll 60 | 61 | 62 | ..\packages\Microsoft.ApplicationInsights.DependencyCollector.2.4.1\lib\net45\Microsoft.AI.DependencyCollector.dll 63 | 64 | 65 | ..\packages\Microsoft.ApplicationInsights.PerfCounterCollector.2.4.1\lib\net45\Microsoft.AI.PerfCounterCollector.dll 66 | 67 | 68 | ..\packages\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.4.0\lib\net45\Microsoft.AI.ServerTelemetryChannel.dll 69 | 70 | 71 | ..\packages\Microsoft.ApplicationInsights.Web.2.4.1\lib\net45\Microsoft.AI.Web.dll 72 | 73 | 74 | ..\packages\Microsoft.ApplicationInsights.WindowsServer.2.4.1\lib\net45\Microsoft.AI.WindowsServer.dll 75 | 76 | 77 | ..\packages\Microsoft.ApplicationInsights.2.4.0\lib\net46\Microsoft.ApplicationInsights.dll 78 | 79 | 80 | ..\packages\Microsoft.AspNet.TelemetryCorrelation.1.0.0\lib\net45\Microsoft.AspNet.TelemetryCorrelation.dll 81 | 82 | 83 | ..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.7\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll 84 | 85 | 86 | 87 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll 88 | 89 | 90 | 91 | 92 | ..\packages\System.Diagnostics.DiagnosticSource.4.4.1\lib\net46\System.Diagnostics.DiagnosticSource.dll 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | True 112 | ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll 113 | 114 | 115 | 116 | 117 | 118 | 119 | True 120 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll 121 | 122 | 123 | True 124 | ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll 125 | 126 | 127 | ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll 128 | 129 | 130 | True 131 | ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll 132 | 133 | 134 | True 135 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll 136 | 137 | 138 | True 139 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll 140 | 141 | 142 | True 143 | ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll 144 | 145 | 146 | ..\packages\WebGrease.1.6.0\lib\WebGrease.dll 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | Global.asax 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | PreserveNewest 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | Web.config 203 | 204 | 205 | Web.config 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | {c8f46fa8-bef3-4592-bd57-e5e9ecfca1b9} 225 | Blip.Data 226 | 227 | 228 | {3a1ff2ca-e0aa-4e04-a082-b8fccd23f8f0} 229 | Blip.Entities 230 | 231 | 232 | 233 | 10.0 234 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | True 247 | True 248 | 61621 249 | / 250 | http://localhost:61621/ 251 | False 252 | False 253 | 254 | 255 | False 256 | 257 | 258 | 259 | 260 | 261 | 262 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 263 | 264 | 265 | 266 | 267 | 273 | --------------------------------------------------------------------------------