├── .gitignore ├── App ├── AttendeeList.sln └── AttendeeList │ ├── .vscode │ ├── launch.json │ └── tasks.json │ ├── AttendeeList.xproj │ ├── Controllers │ ├── AttendeesApiController.cs │ ├── AttendeesController.cs │ └── PlatformController.cs │ ├── Formatters │ └── VCardFormatter.cs │ ├── Models │ ├── Attendee.cs │ └── WorkshopContext.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ ├── Views │ ├── Attendees │ │ ├── Create.cshtml │ │ ├── Delete.cshtml │ │ ├── Details.cshtml │ │ ├── Edit.cshtml │ │ └── Index.cshtml │ └── _ViewImports.cshtml │ ├── appsettings.json │ ├── project.json │ ├── project.lock.json │ ├── tsconfig.json │ ├── web.config │ └── wwwroot │ └── lib │ ├── bootstrap │ ├── .bower.json │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── jquery-validation-unobtrusive │ ├── .bower.json │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── .bower.json │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.js │ │ └── jquery.validate.min.js │ └── jquery │ ├── .bower.json │ ├── LICENSE.txt │ └── dist │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map ├── LICENSE ├── Labs ├── 1. Introduction to the .NET Core SDK.md ├── 2. Introduction to ASP.NET Core.md ├── 3. Introduction to Routing & MVC.md ├── 4. Logging and Diagnostics.md ├── 4.5 Building Middleware.md ├── 5. Dependency Injection & Unit Testing.md ├── 6. Working with Razor Tag Helpers.md ├── 7. APIs with MVC Core.md ├── 7.5 App building - Attendee List.md └── 8. Hosting & Deployment.md ├── README.md ├── Slides └── ASP.NET What and Why.pptx ├── notes └── davidnotes.md └── outline.md /.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 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studo 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | *_i.c 42 | *_p.c 43 | *_i.h 44 | *.ilk 45 | *.meta 46 | *.obj 47 | *.pch 48 | *.pdb 49 | *.pgc 50 | *.pgd 51 | *.rsp 52 | *.sbr 53 | *.tlb 54 | *.tli 55 | *.tlh 56 | *.tmp 57 | *.tmp_proj 58 | *.log 59 | *.vspscc 60 | *.vssscc 61 | .builds 62 | *.pidb 63 | *.svclog 64 | *.scc 65 | 66 | # Chutzpah Test files 67 | _Chutzpah* 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | *.cachefile 76 | 77 | # Visual Studio profiler 78 | *.psess 79 | *.vsp 80 | *.vspx 81 | 82 | # TFS 2012 Local Workspace 83 | $tf/ 84 | 85 | # Guidance Automation Toolkit 86 | *.gpState 87 | 88 | # ReSharper is a .NET coding add-in 89 | _ReSharper*/ 90 | *.[Rr]e[Ss]harper 91 | *.DotSettings.user 92 | 93 | # JustCode is a .NET coding addin-in 94 | .JustCode 95 | 96 | # TeamCity is a build add-in 97 | _TeamCity* 98 | 99 | # DotCover is a Code Coverage Tool 100 | *.dotCover 101 | 102 | # NCrunch 103 | _NCrunch_* 104 | .*crunch*.local.xml 105 | 106 | # MightyMoose 107 | *.mm.* 108 | AutoTest.Net/ 109 | 110 | # Web workbench (sass) 111 | .sass-cache/ 112 | 113 | # Installshield output folder 114 | [Ee]xpress/ 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish/ 128 | 129 | # Publish Web Output 130 | *.[Pp]ublish.xml 131 | *.azurePubxml 132 | # TODO: Comment the next line if you want to checkin your web deploy settings 133 | # but database connection strings (with potential passwords) will be unencrypted 134 | *.pubxml 135 | *.publishproj 136 | 137 | # NuGet Packages 138 | *.nupkg 139 | # The packages folder can be ignored because of Package Restore 140 | **/packages/* 141 | # except build/, which is used as an MSBuild target. 142 | !**/packages/build/ 143 | # Uncomment if necessary however generally it will be regenerated when needed 144 | #!**/packages/repositories.config 145 | 146 | # Windows Azure Build Output 147 | csx/ 148 | *.build.csdef 149 | 150 | # Windows Store app package directory 151 | AppPackages/ 152 | 153 | # Others 154 | *.[Cc]ache 155 | ClientBin/ 156 | [Ss]tyle[Cc]op.* 157 | ~$* 158 | *~ 159 | *.dbmdl 160 | *.dbproj.schemaview 161 | *.pfx 162 | *.publishsettings 163 | node_modules/ 164 | bower_components/ 165 | 166 | # RIA/Silverlight projects 167 | Generated_Code/ 168 | 169 | # Backup & report files from converting an old project file 170 | # to a newer Visual Studio version. Backup files are not needed, 171 | # because we have git ;-) 172 | _UpgradeReport_Files/ 173 | Backup*/ 174 | UpgradeLog*.XML 175 | UpgradeLog*.htm 176 | 177 | # SQL Server files 178 | *.mdf 179 | *.ldf 180 | 181 | # Business Intelligence projects 182 | *.rdl.data 183 | *.bim.layout 184 | *.bim_*.settings 185 | 186 | # Microsoft Fakes 187 | FakesAssemblies/ 188 | 189 | # Node.js Tools for Visual Studio 190 | .ntvs_analysis.dat 191 | 192 | # Visual Studio 6 build log 193 | *.plg 194 | 195 | # Visual Studio 6 workspace options file 196 | *.opt 197 | *.db 198 | -------------------------------------------------------------------------------- /App/AttendeeList.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AttendeeList", "AttendeeList\AttendeeList.xproj", "{D98E4CBE-7E80-47F0-BBB3-F3585F3ED11A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D98E4CBE-7E80-47F0-BBB3-F3585F3ED11A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {D98E4CBE-7E80-47F0-BBB3-F3585F3ED11A}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {D98E4CBE-7E80-47F0-BBB3-F3585F3ED11A}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {D98E4CBE-7E80-47F0-BBB3-F3585F3ED11A}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /App/AttendeeList/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": ".NET Core Launch (console)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "build", 9 | "program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/AttendeeList.dll", 10 | "args": [], 11 | "cwd": "${workspaceRoot}", 12 | "stopAtEntry": false 13 | }, 14 | { 15 | "name": ".NET Core Launch (web)", 16 | "type": "coreclr", 17 | "request": "launch", 18 | "preLaunchTask": "build", 19 | "program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/AttendeeList.dll", 20 | "args": [], 21 | "cwd": "${workspaceRoot}", 22 | "stopAtEntry": false, 23 | "launchBrowser": { 24 | "enabled": true, 25 | "args": "${auto-detect-url}", 26 | "windows": { 27 | "command": "cmd.exe", 28 | "args": "/C start ${auto-detect-url}" 29 | }, 30 | "osx": { 31 | "command": "open" 32 | }, 33 | "linux": { 34 | "command": "xdg-open" 35 | } 36 | } 37 | }, 38 | { 39 | "name": ".NET Core Attach", 40 | "type": "coreclr", 41 | "request": "attach", 42 | "processName": "" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /App/AttendeeList/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "dotnet", 4 | "isShellCommand": true, 5 | "args": [], 6 | "tasks": [ 7 | { 8 | "taskName": "build", 9 | "args": [], 10 | "isBuildCommand": true, 11 | "problemMatcher": "$msCompile" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /App/AttendeeList/AttendeeList.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0.25123 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 9 | d98e4cbe-7e80-47f0-bbb3-f3585f3ed11a 10 | AttendeeList 11 | .\obj 12 | .\bin\ 13 | 14 | 15 | 16 | 2.0 17 | 18 | 19 | -------------------------------------------------------------------------------- /App/AttendeeList/Controllers/AttendeesApiController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.EntityFrameworkCore; 7 | 8 | namespace AttendeeList 9 | { 10 | [Route("/api/attendees")] 11 | public class AttendeesApiController : Controller 12 | { 13 | private readonly WorkshopContext _context; 14 | 15 | public AttendeesApiController(WorkshopContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | [HttpGet] 21 | public Task> Get() 22 | { 23 | return _context.Attendees.ToListAsync(); 24 | } 25 | 26 | [HttpGet("{id:int}")] 27 | public async Task Get(int id) 28 | { 29 | return OkOrNotFound(await _context.Attendees.SingleOrDefaultAsync(a => a.Id == id)); 30 | } 31 | 32 | [HttpPost] 33 | public async Task Create([FromBody]Attendee attendee) 34 | { 35 | if (!ModelState.IsValid) 36 | { 37 | return BadRequest(ModelState); 38 | } 39 | 40 | _context.Attendees.Add(attendee); 41 | await _context.SaveChangesAsync(); 42 | 43 | return CreatedAtAction(nameof(Get), new { id = attendee.Id }, attendee); 44 | } 45 | 46 | [HttpPut("{id:int}")] 47 | public async Task Update([FromBody]Attendee attendee) 48 | { 49 | if (attendee == null) 50 | { 51 | return NotFound(); 52 | } 53 | 54 | if (!ModelState.IsValid) 55 | { 56 | return BadRequest(ModelState); 57 | } 58 | 59 | try 60 | { 61 | _context.Update(attendee); 62 | await _context.SaveChangesAsync(); 63 | return NoContent(); 64 | } 65 | catch (DbUpdateConcurrencyException) 66 | { 67 | if (!AttendeeExists(attendee.Id)) 68 | { 69 | return NotFound(); 70 | } 71 | else 72 | { 73 | throw; 74 | } 75 | } 76 | } 77 | 78 | [HttpDelete("{id:int}")] 79 | public Task Delete(int id) 80 | { 81 | var attendee = new Attendee 82 | { 83 | Id = id 84 | }; 85 | _context.Attach(attendee); 86 | _context.Remove(attendee); 87 | 88 | return _context.SaveChangesAsync(); 89 | } 90 | 91 | private IActionResult OkOrNotFound(object result) 92 | { 93 | if (result == null) 94 | { 95 | return NotFound(); 96 | } 97 | 98 | return Ok(result); 99 | } 100 | 101 | private bool AttendeeExists(int id) 102 | { 103 | return _context.Attendees.Any(e => e.Id == id); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /App/AttendeeList/Controllers/AttendeesController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.EntityFrameworkCore; 7 | 8 | namespace AttendeeList.Controllers 9 | { 10 | [Route("/")] 11 | public class AttendeesController : Controller 12 | { 13 | private readonly WorkshopContext _context; 14 | 15 | public AttendeesController(WorkshopContext context) 16 | { 17 | _context = context; 18 | } 19 | 20 | // GET: / 21 | [HttpGet] 22 | public async Task Index() 23 | { 24 | return View(await _context.Attendees.ToListAsync()); 25 | } 26 | 27 | // GET: Attendees/Details/5 28 | [HttpGet("{id:int}")] 29 | public async Task Details(int? id) 30 | { 31 | if (id == null) 32 | { 33 | return NotFound(); 34 | } 35 | 36 | var attendee = await _context.Attendees.SingleOrDefaultAsync(m => m.Id == id); 37 | if (attendee == null) 38 | { 39 | return NotFound(); 40 | } 41 | 42 | return View(attendee); 43 | } 44 | 45 | [HttpGet("{id:int}/vcard")] 46 | [Produces("text/vcard")] 47 | public async Task VCard(int? id) 48 | { 49 | if (id == null) 50 | { 51 | return NotFound(); 52 | } 53 | 54 | var attendee = await _context.Attendees.SingleOrDefaultAsync(m => m.Id == id); 55 | 56 | if (attendee == null) 57 | { 58 | return NotFound(); 59 | } 60 | 61 | return Ok(attendee); 62 | } 63 | 64 | // GET: Attendees/Create 65 | [HttpGet("create")] 66 | public IActionResult Create() 67 | { 68 | return View(); 69 | } 70 | 71 | // POST: Attendees/Create 72 | [HttpPost("create")] 73 | [ValidateAntiForgeryToken] 74 | public async Task Create(Attendee attendee) 75 | { 76 | if (ModelState.IsValid) 77 | { 78 | _context.Add(attendee); 79 | await _context.SaveChangesAsync(); 80 | return RedirectToAction(nameof(Index)); 81 | } 82 | 83 | return View(attendee); 84 | } 85 | 86 | // GET: Attendees/Edit/5 87 | [HttpGet("{id:int}/edit")] 88 | public async Task Edit(int id) 89 | { 90 | return ViewOrNotFound(await _context.Attendees.SingleOrDefaultAsync(m => m.Id == id)); 91 | } 92 | 93 | // POST: Attendees/Edit/5 94 | [HttpPost("{id:int}/edit")] 95 | [ValidateAntiForgeryToken] 96 | public async Task Edit(int id, Attendee attendee) 97 | { 98 | if (id != attendee.Id) 99 | { 100 | return NotFound(); 101 | } 102 | 103 | if (ModelState.IsValid) 104 | { 105 | try 106 | { 107 | _context.Update(attendee); 108 | await _context.SaveChangesAsync(); 109 | } 110 | catch (DbUpdateConcurrencyException) 111 | { 112 | if (!AttendeeExists(attendee.Id)) 113 | { 114 | return NotFound(); 115 | } 116 | else 117 | { 118 | throw; 119 | } 120 | } 121 | return RedirectToAction(nameof(Index)); 122 | } 123 | return View(attendee); 124 | } 125 | 126 | // GET: Attendees/Delete/5 127 | [HttpGet("{id:int}/delete")] 128 | public Task Delete(int id) => Edit(id); 129 | 130 | // POST: Attendees/Delete/5 131 | [HttpPost("{id:int}/delete"), ActionName("Delete")] 132 | [ValidateAntiForgeryToken] 133 | public async Task DeleteConfirmed(int id) 134 | { 135 | var attendee = await _context.Attendees.SingleOrDefaultAsync(m => m.Id == id); 136 | 137 | _context.Attendees.Remove(attendee); 138 | await _context.SaveChangesAsync(); 139 | 140 | return RedirectToAction(nameof(Index)); 141 | } 142 | 143 | private IActionResult ViewOrNotFound(object model) 144 | { 145 | if (model == null) 146 | { 147 | return NotFound(); 148 | } 149 | 150 | return View(model); 151 | } 152 | 153 | private bool AttendeeExists(int id) 154 | { 155 | return _context.Attendees.Any(e => e.Id == id); 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /App/AttendeeList/Controllers/PlatformController.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace AttendeeList 5 | { 6 | [Route("/api/[controller]")] 7 | public class PlatformController : Controller 8 | { 9 | [HttpGet] 10 | public string Get() 11 | { 12 | return RuntimeInformation.OSDescription; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /App/AttendeeList/Formatters/VCardFormatter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.AspNetCore.Mvc.Formatters; 9 | 10 | namespace AttendeeList 11 | { 12 | public class VCardFormatter : OutputFormatter 13 | { 14 | public VCardFormatter() 15 | { 16 | SupportedMediaTypes.Add("text/vcard"); 17 | } 18 | 19 | protected override bool CanWriteType(Type type) 20 | { 21 | return type == typeof(Attendee); 22 | } 23 | 24 | public override void WriteResponseHeaders(OutputFormatterWriteContext context) 25 | { 26 | var attendee = context.Object as Attendee; 27 | var fileName = $"{attendee.FirstName}_{attendee.LastName}.vcf"; 28 | fileName = new string(fileName.Select(c => Path.GetInvalidPathChars().Contains(c) ? '_' : c).ToArray(), 0, fileName.Length); 29 | context.HttpContext.Response.Headers.Add("content-disposition", $"attachment; filename=\"" + fileName + "\""); 30 | } 31 | 32 | public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context) 33 | { 34 | var attendee = context.Object as Attendee; 35 | 36 | FormattableString card = $@"BEGIN:VCARD 37 | VERSION: 3.0 38 | N:{attendee.LastName};{attendee.FirstName};;; 39 | FN:{attendee.FirstName} {attendee.LastName} 40 | EMAIL;type=INTERNET;type=pref:{attendee.Email} 41 | ORG:{attendee.Company}; 42 | END:VCARD"; 43 | 44 | using (var writer = context.WriterFactory(context.HttpContext.Response.Body, Encoding.UTF8)) 45 | { 46 | return writer.WriteAsync(VCardEncoder.Encode(card)); 47 | } 48 | } 49 | 50 | private class VCardEncoder : IFormatProvider, ICustomFormatter 51 | { 52 | public static VCardEncoder Instance = new VCardEncoder(); 53 | 54 | public static string Encode(FormattableString card) 55 | { 56 | return card.ToString(Instance); 57 | } 58 | 59 | public string Format(string format, object arg, IFormatProvider formatProvider) 60 | { 61 | return Encode(arg); 62 | } 63 | 64 | public object GetFormat(Type formatType) 65 | { 66 | return (formatType == typeof(ICustomFormatter)) ? this : null; 67 | } 68 | 69 | private static string Encode(object arg) 70 | { 71 | return arg.ToString() 72 | .Replace("\\", "\\\\") 73 | .Replace(",", "\\,") 74 | .Replace(";", "\\;"); 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /App/AttendeeList/Models/Attendee.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace AttendeeList 5 | { 6 | public class Attendee 7 | { 8 | public int Id { get; set; } 9 | 10 | [Required] 11 | [Display(Name = "First name")] 12 | public string FirstName { get; set; } 13 | 14 | [Required] 15 | [Display(Name = "Last name")] 16 | public string LastName { get; set; } 17 | 18 | [Display(Name = "E-mail")] 19 | [DataType(DataType.EmailAddress)] 20 | public string Email { get; set; } 21 | 22 | [Required] 23 | public string Company { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /App/AttendeeList/Models/WorkshopContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace AttendeeList 5 | { 6 | public class WorkshopContext : DbContext 7 | { 8 | public WorkshopContext(DbContextOptions options) : base(options) 9 | { 10 | Database.EnsureCreated(); 11 | } 12 | public DbSet Attendees { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /App/AttendeeList/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.AspNetCore.Hosting; 5 | 6 | namespace AttendeeList 7 | { 8 | public class Program 9 | { 10 | public static void Main(string[] args) 11 | { 12 | var host = new WebHostBuilder() 13 | .UseContentRoot(Directory.GetCurrentDirectory()) 14 | .UseKestrel() 15 | .UseIISIntegration() 16 | .UseStartup() 17 | .Build(); 18 | 19 | host.Run(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /App/AttendeeList/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:24737/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /App/AttendeeList/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Builder; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.EntityFrameworkCore; 6 | using Microsoft.Extensions.Logging; 7 | using Microsoft.Extensions.Configuration; 8 | 9 | namespace AttendeeList 10 | { 11 | public class Startup 12 | { 13 | public Startup(IHostingEnvironment environment) 14 | { 15 | Configuration = new ConfigurationBuilder() 16 | .SetBasePath(environment.ContentRootPath) 17 | .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) 18 | .AddEnvironmentVariables() 19 | .Build(); 20 | } 21 | 22 | public IConfiguration Configuration { get; set; } 23 | 24 | public void ConfigureServices(IServiceCollection services) 25 | { 26 | services.AddDbContext(options => 27 | { 28 | options.UseSqlite(Configuration.GetConnectionString("Attendees")); 29 | }); 30 | 31 | services.AddMvc(options => options.OutputFormatters.Add(new VCardFormatter())); 32 | } 33 | 34 | public void Configure(IApplicationBuilder app, IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory) 35 | { 36 | loggerFactory.AddConsole(LogLevel.Debug); 37 | 38 | if (hostingEnvironment.IsDevelopment()) 39 | { 40 | app.UseDeveloperExceptionPage(); 41 | } 42 | 43 | app.UseStaticFiles(); 44 | 45 | app.UseMvc(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /App/AttendeeList/Views/Attendees/Create.cshtml: -------------------------------------------------------------------------------- 1 | @model Attendee 2 | 3 | @{ 4 | Layout = null; 5 | } 6 | 7 | 8 | 9 | 10 | 11 | 12 | Create 13 | 14 | 15 | 16 |
17 |
18 |

Attendee

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 | Back to List 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /App/AttendeeList/Views/Attendees/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @model Attendee 2 | 3 | @{ 4 | Layout = null; 5 | } 6 | 7 | 8 | 9 | 10 | 11 | 12 | Delete 13 | 14 | 15 | 16 |

Are you sure you want to delete this?

17 |
18 |

Attendee

19 |
20 |
21 |
22 | @Html.DisplayNameFor(model => model.FirstName) 23 |
24 |
25 | @Html.DisplayFor(model => model.FirstName) 26 |
27 |
28 | @Html.DisplayNameFor(model => model.LastName) 29 |
30 |
31 | @Html.DisplayFor(model => model.LastName) 32 |
33 |
34 | @Html.DisplayNameFor(model => model.Email) 35 |
36 |
37 | @Html.DisplayFor(model => model.Email) 38 |
39 |
40 | @Html.DisplayNameFor(model => model.Company) 41 |
42 |
43 | @Html.DisplayFor(model => model.Company) 44 |
45 |
46 | 47 |
48 |
49 | | 50 | Back to List 51 |
52 |
53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /App/AttendeeList/Views/Attendees/Details.cshtml: -------------------------------------------------------------------------------- 1 | @model Attendee 2 | 3 | @{ 4 | Layout = null; 5 | } 6 | 7 | 8 | 9 | 10 | 11 | 12 | Details 13 | 14 | 15 | 16 |
17 |

Attendee

18 |
19 |
20 |
21 | @Html.DisplayNameFor(model => model.FirstName) 22 |
23 |
24 | @Html.DisplayFor(model => model.FirstName) 25 |
26 |
27 | @Html.DisplayNameFor(model => model.LastName) 28 |
29 |
30 | @Html.DisplayFor(model => model.LastName) 31 |
32 |
33 | @Html.DisplayNameFor(model => model.Email) 34 |
35 |
36 | @Html.DisplayFor(model => model.Email) 37 |
38 |
39 | @Html.DisplayNameFor(model => model.Company) 40 |
41 |
42 | @Html.DisplayFor(model => model.Company) 43 |
44 |
45 |
46 |
47 | Download vCard | 48 | Edit | 49 | Back to List 50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /App/AttendeeList/Views/Attendees/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @model Attendee 2 | 3 | @{ 4 | Layout = null; 5 | } 6 | 7 | 8 | 9 | 10 | 11 | 12 | Edit 13 | 14 | 15 | 16 |
17 |
18 |

Attendee

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 | Back to List 60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /App/AttendeeList/Views/Attendees/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | @{ 4 | Layout = null; 5 | } 6 | 7 | 8 | 9 | 10 | 11 | 12 | Index 13 | 14 | 15 |

16 | Create New 17 |

18 | 19 | 20 | 21 | 24 | 27 | 30 | 33 | 34 | 35 | 36 | 37 | @foreach (var item in Model) { 38 | 39 | 42 | 45 | 48 | 51 | 57 | 58 | } 59 | 60 |
22 | @Html.DisplayNameFor(model => model.FirstName) 23 | 25 | @Html.DisplayNameFor(model => model.LastName) 26 | 28 | @Html.DisplayNameFor(model => model.Email) 29 | 31 | @Html.DisplayNameFor(model => model.Company) 32 |
40 | @Html.DisplayFor(modelItem => item.FirstName) 41 | 43 | @Html.DisplayFor(modelItem => item.LastName) 44 | 46 | @Html.DisplayFor(modelItem => item.Email) 47 | 49 | @Html.DisplayFor(modelItem => item.Company) 50 | 52 | vCard | 53 | Edit | 54 | Details | 55 | Delete 56 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /App/AttendeeList/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using AttendeeList 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -------------------------------------------------------------------------------- /App/AttendeeList/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings" : { 3 | "Attendees": "Data Source=attendees.db" 4 | } 5 | } -------------------------------------------------------------------------------- /App/AttendeeList/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | 4 | "buildOptions": { 5 | "emitEntryPoint": true, 6 | "preserveCompilationContext": true 7 | }, 8 | 9 | "dependencies": { 10 | "Microsoft.NETCore.App": { 11 | "type": "platform", 12 | "version": "1.0.0-rc2-3002702" 13 | }, 14 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 15 | "Microsoft.AspNetCore.Mvc": "1.0.0-rc2-final", 16 | "Microsoft.AspNetCore.Razor.Tools": { 17 | "version": "1.0.0-preview1-final", 18 | "type": "build" 19 | }, 20 | "Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final", 21 | "Microsoft.AspNetCore.Diagnostics": "1.0.0-rc2-final", 22 | "Microsoft.EntityFrameworkCore.Sqlite": "1.0.0-rc2-final", 23 | "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final", 24 | "Microsoft.Extensions.Configuration.Json": "1.0.0-rc2-final", 25 | "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-rc2-final", 26 | "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final", 27 | "System.Runtime.InteropServices.RuntimeInformation": "4.0.0-rc2-24027", 28 | "Microsoft.VisualStudio.Web.CodeGeneration.Tools": { 29 | "version": "1.0.0-preview1-final", 30 | "type": "build" 31 | }, 32 | "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": { 33 | "version": "1.0.0-preview1-final", 34 | "type": "build" 35 | } 36 | }, 37 | 38 | "tools": { 39 | "Microsoft.AspNetCore.Razor.Tools": { 40 | "version": "1.0.0-preview1-final", 41 | "imports": "portable-net45+win8+dnxcore50" 42 | }, 43 | "Microsoft.VisualStudio.Web.CodeGeneration.Tools": { 44 | "version": "1.0.0-preview1-final", 45 | "imports": [ 46 | "portable-net45+win8+dnxcore50", 47 | "portable-net45+win8" 48 | ] 49 | }, 50 | "Microsoft.AspNetCore.Server.IISIntegration.Tools": { 51 | "version": "1.0.0-preview1-final", 52 | "imports": "portable-net45+win8+dnxcore50" 53 | } 54 | }, 55 | 56 | "frameworks": { 57 | "netcoreapp1.0": { 58 | "imports": [ 59 | "portable-net451+win8" 60 | ] 61 | } 62 | }, 63 | 64 | "publishOptions": { 65 | "include": [ 66 | "wwwroot", 67 | "appsettings.json", 68 | "Views" 69 | ] 70 | }, 71 | 72 | "scripts": { 73 | "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ] 74 | } 75 | } -------------------------------------------------------------------------------- /App/AttendeeList/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "target": "es6" 5 | }, 6 | "files": [ 7 | "wwwroot/app.ts" 8 | ], 9 | "compileOnSave": true 10 | } -------------------------------------------------------------------------------- /App/AttendeeList/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 2" 33 | }, 34 | "version": "3.3.6", 35 | "_release": "3.3.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.6", 39 | "commit": "81df608a40bf0629a1dc08e584849bb1e43e0b7a" 40 | }, 41 | "_source": "git://github.com/twbs/bootstrap.git", 42 | "_target": "3.3.6", 43 | "_originalSource": "bootstrap" 44 | } -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2015 Twitter, Inc 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.6 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | .btn-default, 7 | .btn-primary, 8 | .btn-success, 9 | .btn-info, 10 | .btn-warning, 11 | .btn-danger { 12 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 13 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 14 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | } 16 | .btn-default:active, 17 | .btn-primary:active, 18 | .btn-success:active, 19 | .btn-info:active, 20 | .btn-warning:active, 21 | .btn-danger:active, 22 | .btn-default.active, 23 | .btn-primary.active, 24 | .btn-success.active, 25 | .btn-info.active, 26 | .btn-warning.active, 27 | .btn-danger.active { 28 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 29 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | } 31 | .btn-default.disabled, 32 | .btn-primary.disabled, 33 | .btn-success.disabled, 34 | .btn-info.disabled, 35 | .btn-warning.disabled, 36 | .btn-danger.disabled, 37 | .btn-default[disabled], 38 | .btn-primary[disabled], 39 | .btn-success[disabled], 40 | .btn-info[disabled], 41 | .btn-warning[disabled], 42 | .btn-danger[disabled], 43 | fieldset[disabled] .btn-default, 44 | fieldset[disabled] .btn-primary, 45 | fieldset[disabled] .btn-success, 46 | fieldset[disabled] .btn-info, 47 | fieldset[disabled] .btn-warning, 48 | fieldset[disabled] .btn-danger { 49 | -webkit-box-shadow: none; 50 | box-shadow: none; 51 | } 52 | .btn-default .badge, 53 | .btn-primary .badge, 54 | .btn-success .badge, 55 | .btn-info .badge, 56 | .btn-warning .badge, 57 | .btn-danger .badge { 58 | text-shadow: none; 59 | } 60 | .btn:active, 61 | .btn.active { 62 | background-image: none; 63 | } 64 | .btn-default { 65 | text-shadow: 0 1px 0 #fff; 66 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 67 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 68 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 69 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 70 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 71 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 72 | background-repeat: repeat-x; 73 | border-color: #dbdbdb; 74 | border-color: #ccc; 75 | } 76 | .btn-default:hover, 77 | .btn-default:focus { 78 | background-color: #e0e0e0; 79 | background-position: 0 -15px; 80 | } 81 | .btn-default:active, 82 | .btn-default.active { 83 | background-color: #e0e0e0; 84 | border-color: #dbdbdb; 85 | } 86 | .btn-default.disabled, 87 | .btn-default[disabled], 88 | fieldset[disabled] .btn-default, 89 | .btn-default.disabled:hover, 90 | .btn-default[disabled]:hover, 91 | fieldset[disabled] .btn-default:hover, 92 | .btn-default.disabled:focus, 93 | .btn-default[disabled]:focus, 94 | fieldset[disabled] .btn-default:focus, 95 | .btn-default.disabled.focus, 96 | .btn-default[disabled].focus, 97 | fieldset[disabled] .btn-default.focus, 98 | .btn-default.disabled:active, 99 | .btn-default[disabled]:active, 100 | fieldset[disabled] .btn-default:active, 101 | .btn-default.disabled.active, 102 | .btn-default[disabled].active, 103 | fieldset[disabled] .btn-default.active { 104 | background-color: #e0e0e0; 105 | background-image: none; 106 | } 107 | .btn-primary { 108 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); 109 | background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); 110 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); 111 | background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); 112 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); 113 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 114 | background-repeat: repeat-x; 115 | border-color: #245580; 116 | } 117 | .btn-primary:hover, 118 | .btn-primary:focus { 119 | background-color: #265a88; 120 | background-position: 0 -15px; 121 | } 122 | .btn-primary:active, 123 | .btn-primary.active { 124 | background-color: #265a88; 125 | border-color: #245580; 126 | } 127 | .btn-primary.disabled, 128 | .btn-primary[disabled], 129 | fieldset[disabled] .btn-primary, 130 | .btn-primary.disabled:hover, 131 | .btn-primary[disabled]:hover, 132 | fieldset[disabled] .btn-primary:hover, 133 | .btn-primary.disabled:focus, 134 | .btn-primary[disabled]:focus, 135 | fieldset[disabled] .btn-primary:focus, 136 | .btn-primary.disabled.focus, 137 | .btn-primary[disabled].focus, 138 | fieldset[disabled] .btn-primary.focus, 139 | .btn-primary.disabled:active, 140 | .btn-primary[disabled]:active, 141 | fieldset[disabled] .btn-primary:active, 142 | .btn-primary.disabled.active, 143 | .btn-primary[disabled].active, 144 | fieldset[disabled] .btn-primary.active { 145 | background-color: #265a88; 146 | background-image: none; 147 | } 148 | .btn-success { 149 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 150 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 151 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 152 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 153 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 154 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 155 | background-repeat: repeat-x; 156 | border-color: #3e8f3e; 157 | } 158 | .btn-success:hover, 159 | .btn-success:focus { 160 | background-color: #419641; 161 | background-position: 0 -15px; 162 | } 163 | .btn-success:active, 164 | .btn-success.active { 165 | background-color: #419641; 166 | border-color: #3e8f3e; 167 | } 168 | .btn-success.disabled, 169 | .btn-success[disabled], 170 | fieldset[disabled] .btn-success, 171 | .btn-success.disabled:hover, 172 | .btn-success[disabled]:hover, 173 | fieldset[disabled] .btn-success:hover, 174 | .btn-success.disabled:focus, 175 | .btn-success[disabled]:focus, 176 | fieldset[disabled] .btn-success:focus, 177 | .btn-success.disabled.focus, 178 | .btn-success[disabled].focus, 179 | fieldset[disabled] .btn-success.focus, 180 | .btn-success.disabled:active, 181 | .btn-success[disabled]:active, 182 | fieldset[disabled] .btn-success:active, 183 | .btn-success.disabled.active, 184 | .btn-success[disabled].active, 185 | fieldset[disabled] .btn-success.active { 186 | background-color: #419641; 187 | background-image: none; 188 | } 189 | .btn-info { 190 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 191 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 192 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 193 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 194 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 195 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 196 | background-repeat: repeat-x; 197 | border-color: #28a4c9; 198 | } 199 | .btn-info:hover, 200 | .btn-info:focus { 201 | background-color: #2aabd2; 202 | background-position: 0 -15px; 203 | } 204 | .btn-info:active, 205 | .btn-info.active { 206 | background-color: #2aabd2; 207 | border-color: #28a4c9; 208 | } 209 | .btn-info.disabled, 210 | .btn-info[disabled], 211 | fieldset[disabled] .btn-info, 212 | .btn-info.disabled:hover, 213 | .btn-info[disabled]:hover, 214 | fieldset[disabled] .btn-info:hover, 215 | .btn-info.disabled:focus, 216 | .btn-info[disabled]:focus, 217 | fieldset[disabled] .btn-info:focus, 218 | .btn-info.disabled.focus, 219 | .btn-info[disabled].focus, 220 | fieldset[disabled] .btn-info.focus, 221 | .btn-info.disabled:active, 222 | .btn-info[disabled]:active, 223 | fieldset[disabled] .btn-info:active, 224 | .btn-info.disabled.active, 225 | .btn-info[disabled].active, 226 | fieldset[disabled] .btn-info.active { 227 | background-color: #2aabd2; 228 | background-image: none; 229 | } 230 | .btn-warning { 231 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 232 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 233 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 234 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 235 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 236 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 237 | background-repeat: repeat-x; 238 | border-color: #e38d13; 239 | } 240 | .btn-warning:hover, 241 | .btn-warning:focus { 242 | background-color: #eb9316; 243 | background-position: 0 -15px; 244 | } 245 | .btn-warning:active, 246 | .btn-warning.active { 247 | background-color: #eb9316; 248 | border-color: #e38d13; 249 | } 250 | .btn-warning.disabled, 251 | .btn-warning[disabled], 252 | fieldset[disabled] .btn-warning, 253 | .btn-warning.disabled:hover, 254 | .btn-warning[disabled]:hover, 255 | fieldset[disabled] .btn-warning:hover, 256 | .btn-warning.disabled:focus, 257 | .btn-warning[disabled]:focus, 258 | fieldset[disabled] .btn-warning:focus, 259 | .btn-warning.disabled.focus, 260 | .btn-warning[disabled].focus, 261 | fieldset[disabled] .btn-warning.focus, 262 | .btn-warning.disabled:active, 263 | .btn-warning[disabled]:active, 264 | fieldset[disabled] .btn-warning:active, 265 | .btn-warning.disabled.active, 266 | .btn-warning[disabled].active, 267 | fieldset[disabled] .btn-warning.active { 268 | background-color: #eb9316; 269 | background-image: none; 270 | } 271 | .btn-danger { 272 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 273 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 274 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 275 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 276 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 277 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 278 | background-repeat: repeat-x; 279 | border-color: #b92c28; 280 | } 281 | .btn-danger:hover, 282 | .btn-danger:focus { 283 | background-color: #c12e2a; 284 | background-position: 0 -15px; 285 | } 286 | .btn-danger:active, 287 | .btn-danger.active { 288 | background-color: #c12e2a; 289 | border-color: #b92c28; 290 | } 291 | .btn-danger.disabled, 292 | .btn-danger[disabled], 293 | fieldset[disabled] .btn-danger, 294 | .btn-danger.disabled:hover, 295 | .btn-danger[disabled]:hover, 296 | fieldset[disabled] .btn-danger:hover, 297 | .btn-danger.disabled:focus, 298 | .btn-danger[disabled]:focus, 299 | fieldset[disabled] .btn-danger:focus, 300 | .btn-danger.disabled.focus, 301 | .btn-danger[disabled].focus, 302 | fieldset[disabled] .btn-danger.focus, 303 | .btn-danger.disabled:active, 304 | .btn-danger[disabled]:active, 305 | fieldset[disabled] .btn-danger:active, 306 | .btn-danger.disabled.active, 307 | .btn-danger[disabled].active, 308 | fieldset[disabled] .btn-danger.active { 309 | background-color: #c12e2a; 310 | background-image: none; 311 | } 312 | .thumbnail, 313 | .img-thumbnail { 314 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 315 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 316 | } 317 | .dropdown-menu > li > a:hover, 318 | .dropdown-menu > li > a:focus { 319 | background-color: #e8e8e8; 320 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 321 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 322 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 323 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 324 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 325 | background-repeat: repeat-x; 326 | } 327 | .dropdown-menu > .active > a, 328 | .dropdown-menu > .active > a:hover, 329 | .dropdown-menu > .active > a:focus { 330 | background-color: #2e6da4; 331 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 332 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 333 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 334 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 336 | background-repeat: repeat-x; 337 | } 338 | .navbar-default { 339 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 340 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); 341 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); 342 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 343 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 344 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 345 | background-repeat: repeat-x; 346 | border-radius: 4px; 347 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 348 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 349 | } 350 | .navbar-default .navbar-nav > .open > a, 351 | .navbar-default .navbar-nav > .active > a { 352 | background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 353 | background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 354 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); 355 | background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); 356 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); 357 | background-repeat: repeat-x; 358 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 359 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 360 | } 361 | .navbar-brand, 362 | .navbar-nav > li > a { 363 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 364 | } 365 | .navbar-inverse { 366 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 367 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 368 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 369 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 370 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 371 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 372 | background-repeat: repeat-x; 373 | border-radius: 4px; 374 | } 375 | .navbar-inverse .navbar-nav > .open > a, 376 | .navbar-inverse .navbar-nav > .active > a { 377 | background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); 378 | background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); 379 | background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); 380 | background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); 381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); 382 | background-repeat: repeat-x; 383 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 384 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 385 | } 386 | .navbar-inverse .navbar-brand, 387 | .navbar-inverse .navbar-nav > li > a { 388 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 389 | } 390 | .navbar-static-top, 391 | .navbar-fixed-top, 392 | .navbar-fixed-bottom { 393 | border-radius: 0; 394 | } 395 | @media (max-width: 767px) { 396 | .navbar .navbar-nav .open .dropdown-menu > .active > a, 397 | .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, 398 | .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { 399 | color: #fff; 400 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 401 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 403 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 405 | background-repeat: repeat-x; 406 | } 407 | } 408 | .alert { 409 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 410 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 411 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 412 | } 413 | .alert-success { 414 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 415 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 416 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 417 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 418 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 419 | background-repeat: repeat-x; 420 | border-color: #b2dba1; 421 | } 422 | .alert-info { 423 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 424 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 425 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 426 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 427 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 428 | background-repeat: repeat-x; 429 | border-color: #9acfea; 430 | } 431 | .alert-warning { 432 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 433 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 435 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 437 | background-repeat: repeat-x; 438 | border-color: #f5e79e; 439 | } 440 | .alert-danger { 441 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 442 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 443 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 444 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 445 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 446 | background-repeat: repeat-x; 447 | border-color: #dca7a7; 448 | } 449 | .progress { 450 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 451 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 452 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 453 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 454 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 455 | background-repeat: repeat-x; 456 | } 457 | .progress-bar { 458 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); 459 | background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); 460 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); 461 | background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); 462 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); 463 | background-repeat: repeat-x; 464 | } 465 | .progress-bar-success { 466 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 467 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 468 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 469 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 470 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 471 | background-repeat: repeat-x; 472 | } 473 | .progress-bar-info { 474 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 475 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 476 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 477 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 478 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 479 | background-repeat: repeat-x; 480 | } 481 | .progress-bar-warning { 482 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 483 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 484 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 485 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 486 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 487 | background-repeat: repeat-x; 488 | } 489 | .progress-bar-danger { 490 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 491 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 492 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 493 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 494 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 495 | background-repeat: repeat-x; 496 | } 497 | .progress-bar-striped { 498 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 499 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 500 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 501 | } 502 | .list-group { 503 | border-radius: 4px; 504 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 505 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 506 | } 507 | .list-group-item.active, 508 | .list-group-item.active:hover, 509 | .list-group-item.active:focus { 510 | text-shadow: 0 -1px 0 #286090; 511 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); 512 | background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); 513 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); 514 | background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); 515 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); 516 | background-repeat: repeat-x; 517 | border-color: #2b669a; 518 | } 519 | .list-group-item.active .badge, 520 | .list-group-item.active:hover .badge, 521 | .list-group-item.active:focus .badge { 522 | text-shadow: none; 523 | } 524 | .panel { 525 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 526 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 527 | } 528 | .panel-default > .panel-heading { 529 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 530 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 531 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 532 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 533 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 534 | background-repeat: repeat-x; 535 | } 536 | .panel-primary > .panel-heading { 537 | background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 538 | background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); 539 | background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); 540 | background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); 541 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); 542 | background-repeat: repeat-x; 543 | } 544 | .panel-success > .panel-heading { 545 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 546 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 547 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 548 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 549 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 550 | background-repeat: repeat-x; 551 | } 552 | .panel-info > .panel-heading { 553 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 554 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 555 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 556 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 557 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 558 | background-repeat: repeat-x; 559 | } 560 | .panel-warning > .panel-heading { 561 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 562 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 563 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 564 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 565 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 566 | background-repeat: repeat-x; 567 | } 568 | .panel-danger > .panel-heading { 569 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 570 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 571 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 572 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 573 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 574 | background-repeat: repeat-x; 575 | } 576 | .well { 577 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 578 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 579 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 580 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 581 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 582 | background-repeat: repeat-x; 583 | border-color: #dcdcdc; 584 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 585 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 586 | } 587 | /*# sourceMappingURL=bootstrap-theme.css.map */ 588 | -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.6 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} 6 | /*# sourceMappingURL=bootstrap-theme.min.css.map */ -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":";;;;AAmBA,YAAA,aAAA,UAAA,aAAA,aAAA,aAME,YAAA,EAAA,KAAA,EAAA,eC2CA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBDvCR,mBAAA,mBAAA,oBAAA,oBAAA,iBAAA,iBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBAAA,oBCsCA,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBDlCR,qBAAA,sBAAA,sBAAA,uBAAA,mBAAA,oBAAA,sBAAA,uBAAA,sBAAA,uBAAA,sBAAA,uBAAA,+BAAA,gCAAA,6BAAA,gCAAA,gCAAA,gCCiCA,mBAAA,KACQ,WAAA,KDlDV,mBAAA,oBAAA,iBAAA,oBAAA,oBAAA,oBAuBI,YAAA,KAyCF,YAAA,YAEE,iBAAA,KAKJ,aErEI,YAAA,EAAA,IAAA,EAAA,KACA,iBAAA,iDACA,iBAAA,4CAAA,iBAAA,qEAEA,iBAAA,+CCnBF,OAAA,+GH4CA,OAAA,0DACA,kBAAA,SAuC2C,aAAA,QAA2B,aAAA,KArCtE,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAgBN,aEtEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAiBN,aEvEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAkBN,UExEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,gBAAA,gBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,iBAAA,iBAEE,iBAAA,QACA,aAAA,QAMA,mBAAA,0BAAA,yBAAA,0BAAA,yBAAA,yBAAA,oBAAA,2BAAA,0BAAA,2BAAA,0BAAA,0BAAA,6BAAA,oCAAA,mCAAA,oCAAA,mCAAA,mCAME,iBAAA,QACA,iBAAA,KAmBN,aEzEI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,mBAAA,mBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,oBAAA,oBAEE,iBAAA,QACA,aAAA,QAMA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,uBAAA,8BAAA,6BAAA,8BAAA,6BAAA,6BAAA,gCAAA,uCAAA,sCAAA,uCAAA,sCAAA,sCAME,iBAAA,QACA,iBAAA,KAoBN,YE1EI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDAEA,OAAA,+GCnBF,OAAA,0DH4CA,kBAAA,SACA,aAAA,QAEA,kBAAA,kBAEE,iBAAA,QACA,oBAAA,EAAA,MAGF,mBAAA,mBAEE,iBAAA,QACA,aAAA,QAMA,qBAAA,4BAAA,2BAAA,4BAAA,2BAAA,2BAAA,sBAAA,6BAAA,4BAAA,6BAAA,4BAAA,4BAAA,+BAAA,sCAAA,qCAAA,sCAAA,qCAAA,qCAME,iBAAA,QACA,iBAAA,KA2BN,eAAA,WClCE,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBD2CV,0BAAA,0BE3FI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GF0FF,kBAAA,SAEF,yBAAA,+BAAA,+BEhGI,iBAAA,QACA,iBAAA,oDACA,iBAAA,+CAAA,iBAAA,wEACA,iBAAA,kDACA,OAAA,+GFgGF,kBAAA,SASF,gBE7GI,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SH+HA,cAAA,ICjEA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,iBD6DV,sCAAA,oCE7GI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,iBD0EV,cAAA,iBAEE,YAAA,EAAA,IAAA,EAAA,sBAIF,gBEhII,iBAAA,iDACA,iBAAA,4CACA,iBAAA,qEAAA,iBAAA,+CACA,OAAA,+GACA,OAAA,0DCnBF,kBAAA,SHkJA,cAAA,IAHF,sCAAA,oCEhII,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SD2CF,mBAAA,MAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBDgFV,8BAAA,iCAYI,YAAA,EAAA,KAAA,EAAA,gBAKJ,qBAAA,kBAAA,mBAGE,cAAA,EAqBF,yBAfI,mDAAA,yDAAA,yDAGE,MAAA,KE7JF,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,UFqKJ,OACE,YAAA,EAAA,IAAA,EAAA,qBC3HA,mBAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,MAAA,EAAA,IAAA,EAAA,sBAAA,EAAA,IAAA,IAAA,gBDsIV,eEtLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAKF,YEvLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAMF,eExLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAOF,cEzLI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF8KF,aAAA,QAeF,UEjMI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFuMJ,cE3MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFwMJ,sBE5MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyMJ,mBE7MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0MJ,sBE9MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2MJ,qBE/MI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF+MJ,sBElLI,iBAAA,yKACA,iBAAA,oKACA,iBAAA,iKFyLJ,YACE,cAAA,IC9KA,mBAAA,EAAA,IAAA,IAAA,iBACQ,WAAA,EAAA,IAAA,IAAA,iBDgLV,wBAAA,8BAAA,8BAGE,YAAA,EAAA,KAAA,EAAA,QEnOE,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFiOF,aAAA,QALF,+BAAA,qCAAA,qCAQI,YAAA,KAUJ,OCnME,mBAAA,EAAA,IAAA,IAAA,gBACQ,WAAA,EAAA,IAAA,IAAA,gBD4MV,8BE5PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFyPJ,8BE7PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF0PJ,8BE9PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF2PJ,2BE/PI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF4PJ,8BEhQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SF6PJ,6BEjQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFoQJ,MExQI,iBAAA,oDACA,iBAAA,+CACA,iBAAA,wEAAA,iBAAA,kDACA,OAAA,+GACA,kBAAA,SFsQF,aAAA,QC3NA,mBAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA,qBACQ,WAAA,MAAA,EAAA,IAAA,IAAA,gBAAA,EAAA,IAAA,EAAA"} -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/aspnetcore-workshop/2b4cabb8d71551d0662f3d418c053b92c0785ed0/App/AttendeeList/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/aspnetcore-workshop/2b4cabb8d71551d0662f3d418c053b92c0785ed0/App/AttendeeList/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/aspnetcore-workshop/2b4cabb8d71551d0662f3d418c053b92c0785ed0/App/AttendeeList/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/aspnetcore-workshop/2b4cabb8d71551d0662f3d418c053b92c0785ed0/App/AttendeeList/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js: -------------------------------------------------------------------------------- 1 | /*! 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | 6 | /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ 7 | /*global document: false, jQuery: false */ 8 | 9 | (function ($) { 10 | var $jQval = $.validator, 11 | adapters, 12 | data_validation = "unobtrusiveValidation"; 13 | 14 | function setValidationValues(options, ruleName, value) { 15 | options.rules[ruleName] = value; 16 | if (options.message) { 17 | options.messages[ruleName] = options.message; 18 | } 19 | } 20 | 21 | function splitAndTrim(value) { 22 | return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); 23 | } 24 | 25 | function escapeAttributeValue(value) { 26 | // As mentioned on http://api.jquery.com/category/selectors/ 27 | return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1"); 28 | } 29 | 30 | function getModelPrefix(fieldName) { 31 | return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); 32 | } 33 | 34 | function appendModelPrefix(value, prefix) { 35 | if (value.indexOf("*.") === 0) { 36 | value = value.replace("*.", prefix); 37 | } 38 | return value; 39 | } 40 | 41 | function onError(error, inputElement) { // 'this' is the form element 42 | var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), 43 | replaceAttrValue = container.attr("data-valmsg-replace"), 44 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; 45 | 46 | container.removeClass("field-validation-valid").addClass("field-validation-error"); 47 | error.data("unobtrusiveContainer", container); 48 | 49 | if (replace) { 50 | container.empty(); 51 | error.removeClass("input-validation-error").appendTo(container); 52 | } 53 | else { 54 | error.hide(); 55 | } 56 | } 57 | 58 | function onErrors(event, validator) { // 'this' is the form element 59 | var container = $(this).find("[data-valmsg-summary=true]"), 60 | list = container.find("ul"); 61 | 62 | if (list && list.length && validator.errorList.length) { 63 | list.empty(); 64 | container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); 65 | 66 | $.each(validator.errorList, function () { 67 | $("
  • ").html(this.message).appendTo(list); 68 | }); 69 | } 70 | } 71 | 72 | function onSuccess(error) { // 'this' is the form element 73 | var container = error.data("unobtrusiveContainer"); 74 | 75 | if (container) { 76 | var replaceAttrValue = container.attr("data-valmsg-replace"), 77 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; 78 | 79 | container.addClass("field-validation-valid").removeClass("field-validation-error"); 80 | error.removeData("unobtrusiveContainer"); 81 | 82 | if (replace) { 83 | container.empty(); 84 | } 85 | } 86 | } 87 | 88 | function onReset(event) { // 'this' is the form element 89 | var $form = $(this), 90 | key = '__jquery_unobtrusive_validation_form_reset'; 91 | if ($form.data(key)) { 92 | return; 93 | } 94 | // Set a flag that indicates we're currently resetting the form. 95 | $form.data(key, true); 96 | try { 97 | $form.data("validator").resetForm(); 98 | } finally { 99 | $form.removeData(key); 100 | } 101 | 102 | $form.find(".validation-summary-errors") 103 | .addClass("validation-summary-valid") 104 | .removeClass("validation-summary-errors"); 105 | $form.find(".field-validation-error") 106 | .addClass("field-validation-valid") 107 | .removeClass("field-validation-error") 108 | .removeData("unobtrusiveContainer") 109 | .find(">*") // If we were using valmsg-replace, get the underlying error 110 | .removeData("unobtrusiveContainer"); 111 | } 112 | 113 | function validationInfo(form) { 114 | var $form = $(form), 115 | result = $form.data(data_validation), 116 | onResetProxy = $.proxy(onReset, form), 117 | defaultOptions = $jQval.unobtrusive.options || {}, 118 | execInContext = function (name, args) { 119 | var func = defaultOptions[name]; 120 | func && $.isFunction(func) && func.apply(form, args); 121 | } 122 | 123 | if (!result) { 124 | result = { 125 | options: { // options structure passed to jQuery Validate's validate() method 126 | errorClass: defaultOptions.errorClass || "input-validation-error", 127 | errorElement: defaultOptions.errorElement || "span", 128 | errorPlacement: function () { 129 | onError.apply(form, arguments); 130 | execInContext("errorPlacement", arguments); 131 | }, 132 | invalidHandler: function () { 133 | onErrors.apply(form, arguments); 134 | execInContext("invalidHandler", arguments); 135 | }, 136 | messages: {}, 137 | rules: {}, 138 | success: function () { 139 | onSuccess.apply(form, arguments); 140 | execInContext("success", arguments); 141 | } 142 | }, 143 | attachValidation: function () { 144 | $form 145 | .off("reset." + data_validation, onResetProxy) 146 | .on("reset." + data_validation, onResetProxy) 147 | .validate(this.options); 148 | }, 149 | validate: function () { // a validation function that is called by unobtrusive Ajax 150 | $form.validate(); 151 | return $form.valid(); 152 | } 153 | }; 154 | $form.data(data_validation, result); 155 | } 156 | 157 | return result; 158 | } 159 | 160 | $jQval.unobtrusive = { 161 | adapters: [], 162 | 163 | parseElement: function (element, skipAttach) { 164 | /// 165 | /// Parses a single HTML element for unobtrusive validation attributes. 166 | /// 167 | /// The HTML element to be parsed. 168 | /// [Optional] true to skip attaching the 169 | /// validation to the form. If parsing just this single element, you should specify true. 170 | /// If parsing several elements, you should specify false, and manually attach the validation 171 | /// to the form when you are finished. The default is false. 172 | var $element = $(element), 173 | form = $element.parents("form")[0], 174 | valInfo, rules, messages; 175 | 176 | if (!form) { // Cannot do client-side validation without a form 177 | return; 178 | } 179 | 180 | valInfo = validationInfo(form); 181 | valInfo.options.rules[element.name] = rules = {}; 182 | valInfo.options.messages[element.name] = messages = {}; 183 | 184 | $.each(this.adapters, function () { 185 | var prefix = "data-val-" + this.name, 186 | message = $element.attr(prefix), 187 | paramValues = {}; 188 | 189 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) 190 | prefix += "-"; 191 | 192 | $.each(this.params, function () { 193 | paramValues[this] = $element.attr(prefix + this); 194 | }); 195 | 196 | this.adapt({ 197 | element: element, 198 | form: form, 199 | message: message, 200 | params: paramValues, 201 | rules: rules, 202 | messages: messages 203 | }); 204 | } 205 | }); 206 | 207 | $.extend(rules, { "__dummy__": true }); 208 | 209 | if (!skipAttach) { 210 | valInfo.attachValidation(); 211 | } 212 | }, 213 | 214 | parse: function (selector) { 215 | /// 216 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated 217 | /// with the [data-val=true] attribute value and enables validation according to the data-val-* 218 | /// attribute values. 219 | /// 220 | /// Any valid jQuery selector. 221 | 222 | // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one 223 | // element with data-val=true 224 | var $selector = $(selector), 225 | $forms = $selector.parents() 226 | .addBack() 227 | .filter("form") 228 | .add($selector.find("form")) 229 | .has("[data-val=true]"); 230 | 231 | $selector.find("[data-val=true]").each(function () { 232 | $jQval.unobtrusive.parseElement(this, true); 233 | }); 234 | 235 | $forms.each(function () { 236 | var info = validationInfo(this); 237 | if (info) { 238 | info.attachValidation(); 239 | } 240 | }); 241 | } 242 | }; 243 | 244 | adapters = $jQval.unobtrusive.adapters; 245 | 246 | adapters.add = function (adapterName, params, fn) { 247 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. 248 | /// The name of the adapter to be added. This matches the name used 249 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 250 | /// [Optional] An array of parameter names (strings) that will 251 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and 252 | /// mmmm is the parameter name). 253 | /// The function to call, which adapts the values from the HTML 254 | /// attributes into jQuery Validate rules and/or messages. 255 | /// 256 | if (!fn) { // Called with no params, just a function 257 | fn = params; 258 | params = []; 259 | } 260 | this.push({ name: adapterName, params: params, adapt: fn }); 261 | return this; 262 | }; 263 | 264 | adapters.addBool = function (adapterName, ruleName) { 265 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 266 | /// the jQuery Validate validation rule has no parameter values. 267 | /// The name of the adapter to be added. This matches the name used 268 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 269 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 270 | /// of adapterName will be used instead. 271 | /// 272 | return this.add(adapterName, function (options) { 273 | setValidationValues(options, ruleName || adapterName, true); 274 | }); 275 | }; 276 | 277 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { 278 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 279 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and 280 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max. 281 | /// The name of the adapter to be added. This matches the name used 282 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 283 | /// The name of the jQuery Validate rule to be used when you only 284 | /// have a minimum value. 285 | /// The name of the jQuery Validate rule to be used when you only 286 | /// have a maximum value. 287 | /// The name of the jQuery Validate rule to be used when you 288 | /// have both a minimum and maximum value. 289 | /// [Optional] The name of the HTML attribute that 290 | /// contains the minimum value. The default is "min". 291 | /// [Optional] The name of the HTML attribute that 292 | /// contains the maximum value. The default is "max". 293 | /// 294 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { 295 | var min = options.params.min, 296 | max = options.params.max; 297 | 298 | if (min && max) { 299 | setValidationValues(options, minMaxRuleName, [min, max]); 300 | } 301 | else if (min) { 302 | setValidationValues(options, minRuleName, min); 303 | } 304 | else if (max) { 305 | setValidationValues(options, maxRuleName, max); 306 | } 307 | }); 308 | }; 309 | 310 | adapters.addSingleVal = function (adapterName, attribute, ruleName) { 311 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 312 | /// the jQuery Validate validation rule has a single value. 313 | /// The name of the adapter to be added. This matches the name used 314 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). 315 | /// [Optional] The name of the HTML attribute that contains the value. 316 | /// The default is "val". 317 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 318 | /// of adapterName will be used instead. 319 | /// 320 | return this.add(adapterName, [attribute || "val"], function (options) { 321 | setValidationValues(options, ruleName || adapterName, options.params[attribute]); 322 | }); 323 | }; 324 | 325 | $jQval.addMethod("__dummy__", function (value, element, params) { 326 | return true; 327 | }); 328 | 329 | $jQval.addMethod("regex", function (value, element, params) { 330 | var match; 331 | if (this.optional(element)) { 332 | return true; 333 | } 334 | 335 | match = new RegExp(params).exec(value); 336 | return (match && (match.index === 0) && (match[0].length === value.length)); 337 | }); 338 | 339 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { 340 | var match; 341 | if (nonalphamin) { 342 | match = value.match(/\W/g); 343 | match = match && match.length >= nonalphamin; 344 | } 345 | return match; 346 | }); 347 | 348 | if ($jQval.methods.extension) { 349 | adapters.addSingleVal("accept", "mimtype"); 350 | adapters.addSingleVal("extension", "extension"); 351 | } else { 352 | // for backward compatibility, when the 'extension' validation method does not exist, such as with versions 353 | // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for 354 | // validating the extension, and ignore mime-type validations as they are not supported. 355 | adapters.addSingleVal("extension", "extension", "accept"); 356 | } 357 | 358 | adapters.addSingleVal("regex", "pattern"); 359 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); 360 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); 361 | adapters.addMinMax("minlength", "minlength").addMinMax("maxlength", "minlength", "maxlength"); 362 | adapters.add("equalto", ["other"], function (options) { 363 | var prefix = getModelPrefix(options.element.name), 364 | other = options.params.other, 365 | fullOtherName = appendModelPrefix(other, prefix), 366 | element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; 367 | 368 | setValidationValues(options, "equalTo", element); 369 | }); 370 | adapters.add("required", function (options) { 371 | // jQuery Validate equates "required" with "mandatory" for checkbox elements 372 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { 373 | setValidationValues(options, "required", true); 374 | } 375 | }); 376 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) { 377 | var value = { 378 | url: options.params.url, 379 | type: options.params.type || "GET", 380 | data: {} 381 | }, 382 | prefix = getModelPrefix(options.element.name); 383 | 384 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { 385 | var paramName = appendModelPrefix(fieldName, prefix); 386 | value.data[paramName] = function () { 387 | var field = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']"); 388 | // For checkboxes and radio buttons, only pick up values from checked fields. 389 | if (field.is(":checkbox")) { 390 | return field.filter(":checked").val() || field.filter(":hidden").val() || ''; 391 | } 392 | else if (field.is(":radio")) { 393 | return field.filter(":checked").val() || ''; 394 | } 395 | return field.val(); 396 | }; 397 | }); 398 | 399 | setValidationValues(options, "remote", value); 400 | }); 401 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { 402 | if (options.params.min) { 403 | setValidationValues(options, "minlength", options.params.min); 404 | } 405 | if (options.params.nonalphamin) { 406 | setValidationValues(options, "nonalphamin", options.params.nonalphamin); 407 | } 408 | if (options.params.regex) { 409 | setValidationValues(options, "regex", options.params.regex); 410 | } 411 | }); 412 | 413 | $(function () { 414 | $jQval.unobtrusive.parse(document); 415 | }); 416 | }(jQuery)); -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/jquery-validation/dist/additional-methods.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Validation Plugin - v1.14.0 - 6/30/2015 2 | * http://jqueryvalidation.org/ 3 | * Copyright (c) 2015 Jörn Zaefferer; Licensed MIT */ 4 | !function(a){"function"==typeof define&&define.amd?define(["jquery","./jquery.validate.min"],a):a(jQuery)}(function(a){!function(){function b(a){return a.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," ").replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g,"")}a.validator.addMethod("maxWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length<=d},a.validator.format("Please enter {0} words or less.")),a.validator.addMethod("minWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length>=d},a.validator.format("Please enter at least {0} words.")),a.validator.addMethod("rangeWords",function(a,c,d){var e=b(a),f=/\b\w+\b/g;return this.optional(c)||e.match(f).length>=d[0]&&e.match(f).length<=d[1]},a.validator.format("Please enter between {0} and {1} words."))}(),a.validator.addMethod("accept",function(b,c,d){var e,f,g="string"==typeof d?d.replace(/\s/g,"").replace(/,/g,"|"):"image/*",h=this.optional(c);if(h)return h;if("file"===a(c).attr("type")&&(g=g.replace(/\*/g,".*"),c.files&&c.files.length))for(e=0;ec;c++)d=h-c,e=f.substring(c,c+1),g+=d*e;return g%11===0},"Please specify a valid bank account number"),a.validator.addMethod("bankorgiroaccountNL",function(b,c){return this.optional(c)||a.validator.methods.bankaccountNL.call(this,b,c)||a.validator.methods.giroaccountNL.call(this,b,c)},"Please specify a valid bank or giro account number"),a.validator.addMethod("bic",function(a,b){return this.optional(b)||/^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test(a)},"Please specify a valid BIC code"),a.validator.addMethod("cifES",function(a){"use strict";var b,c,d,e,f,g,h=[];if(a=a.toUpperCase(),!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)"))return!1;for(d=0;9>d;d++)h[d]=parseInt(a.charAt(d),10);for(c=h[2]+h[4]+h[6],e=1;8>e;e+=2)f=(2*h[e]).toString(),g=f.charAt(1),c+=parseInt(f.charAt(0),10)+(""===g?0:parseInt(g,10));return/^[ABCDEFGHJNPQRSUVW]{1}/.test(a)?(c+="",b=10-parseInt(c.charAt(c.length-1),10),a+=b,h[8].toString()===String.fromCharCode(64+b)||h[8].toString()===a.charAt(a.length-1)):!1},"Please specify a valid CIF number."),a.validator.addMethod("cpfBR",function(a){if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var b,c,d,e,f=0;if(b=parseInt(a.substring(9,10),10),c=parseInt(a.substring(10,11),10),d=function(a,b){var c=10*a%11;return(10===c||11===c)&&(c=0),c===b},""===a||"00000000000"===a||"11111111111"===a||"22222222222"===a||"33333333333"===a||"44444444444"===a||"55555555555"===a||"66666666666"===a||"77777777777"===a||"88888888888"===a||"99999999999"===a)return!1;for(e=1;9>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(11-e);if(d(f,b)){for(f=0,e=1;10>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(12-e);return d(f,c)}return!1},"Please specify a valid CPF number"),a.validator.addMethod("creditcardtypes",function(a,b,c){if(/[^0-9\-]+/.test(a))return!1;a=a.replace(/\D/g,"");var d=0;return c.mastercard&&(d|=1),c.visa&&(d|=2),c.amex&&(d|=4),c.dinersclub&&(d|=8),c.enroute&&(d|=16),c.discover&&(d|=32),c.jcb&&(d|=64),c.unknown&&(d|=128),c.all&&(d=255),1&d&&/^(5[12345])/.test(a)?16===a.length:2&d&&/^(4)/.test(a)?16===a.length:4&d&&/^(3[47])/.test(a)?15===a.length:8&d&&/^(3(0[012345]|[68]))/.test(a)?14===a.length:16&d&&/^(2(014|149))/.test(a)?15===a.length:32&d&&/^(6011)/.test(a)?16===a.length:64&d&&/^(3)/.test(a)?16===a.length:64&d&&/^(2131|1800)/.test(a)?15===a.length:128&d?!0:!1},"Please enter a valid credit card number."),a.validator.addMethod("currency",function(a,b,c){var d,e="string"==typeof c,f=e?c:c[0],g=e?!0:c[1];return f=f.replace(/,/g,""),f=g?f+"]":f+"]?",d="^["+f+"([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$",d=new RegExp(d),this.optional(b)||d.test(a)},"Please specify a valid currency"),a.validator.addMethod("dateFA",function(a,b){return this.optional(b)||/^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(a)},a.validator.messages.date),a.validator.addMethod("dateITA",function(a,b){var c,d,e,f,g,h=!1,i=/^\d{1,2}\/\d{1,2}\/\d{4}$/;return i.test(a)?(c=a.split("/"),d=parseInt(c[0],10),e=parseInt(c[1],10),f=parseInt(c[2],10),g=new Date(Date.UTC(f,e-1,d,12,0,0,0)),h=g.getUTCFullYear()===f&&g.getUTCMonth()===e-1&&g.getUTCDate()===d?!0:!1):h=!1,this.optional(b)||h},a.validator.messages.date),a.validator.addMethod("dateNL",function(a,b){return this.optional(b)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(a)},a.validator.messages.date),a.validator.addMethod("extension",function(a,b,c){return c="string"==typeof c?c.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(b)||a.match(new RegExp("\\.("+c+")$","i"))},a.validator.format("Please enter a value with a valid extension.")),a.validator.addMethod("giroaccountNL",function(a,b){return this.optional(b)||/^[0-9]{1,7}$/.test(a)},"Please specify a valid giro account number"),a.validator.addMethod("iban",function(a,b){if(this.optional(b))return!0;var c,d,e,f,g,h,i,j,k,l=a.replace(/ /g,"").toUpperCase(),m="",n=!0,o="",p="";if(c=l.substring(0,2),h={AL:"\\d{8}[\\dA-Z]{16}",AD:"\\d{8}[\\dA-Z]{12}",AT:"\\d{16}",AZ:"[\\dA-Z]{4}\\d{20}",BE:"\\d{12}",BH:"[A-Z]{4}[\\dA-Z]{14}",BA:"\\d{16}",BR:"\\d{23}[A-Z][\\dA-Z]",BG:"[A-Z]{4}\\d{6}[\\dA-Z]{8}",CR:"\\d{17}",HR:"\\d{17}",CY:"\\d{8}[\\dA-Z]{16}",CZ:"\\d{20}",DK:"\\d{14}",DO:"[A-Z]{4}\\d{20}",EE:"\\d{16}",FO:"\\d{14}",FI:"\\d{14}",FR:"\\d{10}[\\dA-Z]{11}\\d{2}",GE:"[\\dA-Z]{2}\\d{16}",DE:"\\d{18}",GI:"[A-Z]{4}[\\dA-Z]{15}",GR:"\\d{7}[\\dA-Z]{16}",GL:"\\d{14}",GT:"[\\dA-Z]{4}[\\dA-Z]{20}",HU:"\\d{24}",IS:"\\d{22}",IE:"[\\dA-Z]{4}\\d{14}",IL:"\\d{19}",IT:"[A-Z]\\d{10}[\\dA-Z]{12}",KZ:"\\d{3}[\\dA-Z]{13}",KW:"[A-Z]{4}[\\dA-Z]{22}",LV:"[A-Z]{4}[\\dA-Z]{13}",LB:"\\d{4}[\\dA-Z]{20}",LI:"\\d{5}[\\dA-Z]{12}",LT:"\\d{16}",LU:"\\d{3}[\\dA-Z]{13}",MK:"\\d{3}[\\dA-Z]{10}\\d{2}",MT:"[A-Z]{4}\\d{5}[\\dA-Z]{18}",MR:"\\d{23}",MU:"[A-Z]{4}\\d{19}[A-Z]{3}",MC:"\\d{10}[\\dA-Z]{11}\\d{2}",MD:"[\\dA-Z]{2}\\d{18}",ME:"\\d{18}",NL:"[A-Z]{4}\\d{10}",NO:"\\d{11}",PK:"[\\dA-Z]{4}\\d{16}",PS:"[\\dA-Z]{4}\\d{21}",PL:"\\d{24}",PT:"\\d{21}",RO:"[A-Z]{4}[\\dA-Z]{16}",SM:"[A-Z]\\d{10}[\\dA-Z]{12}",SA:"\\d{2}[\\dA-Z]{18}",RS:"\\d{18}",SK:"\\d{20}",SI:"\\d{15}",ES:"\\d{20}",SE:"\\d{20}",CH:"\\d{5}[\\dA-Z]{12}",TN:"\\d{20}",TR:"\\d{5}[\\dA-Z]{17}",AE:"\\d{3}\\d{16}",GB:"[A-Z]{4}\\d{14}",VG:"[\\dA-Z]{4}\\d{16}"},g=h[c],"undefined"!=typeof g&&(i=new RegExp("^[A-Z]{2}\\d{2}"+g+"$",""),!i.test(l)))return!1;for(d=l.substring(4,l.length)+l.substring(0,4),j=0;j9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("nieES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[T]{1}/.test(a)?a[8]===/^[T]{1}[A-Z0-9]{8}$/.test(a):/^[XYZ]{1}/.test(a)?a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.replace("X","0").replace("Y","1").replace("Z","2").substring(0,8)%23):!1:!1},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):/^[KLM]{1}/.test(a)?a[8]===String.fromCharCode(64):!1:!1},"Please specify a valid NIF number."),jQuery.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return this.optional(b)?!0:("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=e||"undefined"==typeof c.caseSensitive?!1:c.caseSensitive,g=e||"undefined"==typeof c.includeTerritories?!1:c.includeTerritories,h=e||"undefined"==typeof c.includeMilitary?!1:c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;17>b;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),e=c.settings.submitHandler.call(c,c.currentForm,b),c.submitButton&&d.remove(),void 0!==e?e:!1):!0}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,d=d.concat(c.errorList)}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(b,c){i[c]=f[c],delete f[c],"required"===c&&a(j).removeAttr("aria-required")}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g),a(j).attr("aria-required","true")),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}),a.extend(a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){return!!a.trim(""+a(b).val())},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||-1!==a.inArray(c.keyCode,d)||(b.name in this.submitted||b===this.lastElement)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date ( ISO ).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler),a(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required","true")},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c=this.clean(b),d=this.validationTargetFor(c),e=!0;return this.lastElement=d,void 0===d?delete this.invalid[c.name]:(this.prepareElement(d),this.currentElements=a(d),e=this.check(d)!==!1,e?delete this.invalid[d.name]:this.invalid[d.name]=!0),a(b).attr("aria-invalid",!e),this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),e},showErrors:function(b){if(b){a.extend(this.errorMap,b),this.errorList=[];for(var c in b)this.errorList.push({message:b[c],element:this.findByName(c)[0]});this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors();var b,c=this.elements().removeData("previousValue").removeAttr("aria-invalid");if(this.settings.unhighlight)for(b=0;c[b];b++)this.settings.unhighlight.call(this,c[b],this.settings.errorClass,"");else c.removeClass(this.settings.errorClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){return!this.name&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in c||!b.objectLength(a(this).rules())?!1:(c[this.name]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([]),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d=a(b),e=b.type;return"radio"===e||"checkbox"===e?this.findByName(b.name).filter(":checked").val():"number"===e&&"undefined"!=typeof b.validity?b.validity.badInput?!1:d.val():(c=d.val(),"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f=a(b).rules(),g=a.map(f,function(a,b){return b}).length,h=!1,i=this.elementValue(b);for(d in f){e={method:d,parameters:f[d]};try{if(c=a.validator.methods[d].call(this,i,b,e.parameters),"dependency-mismatch"===c&&1===g){h=!0;continue}if(h=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(j){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",j),j instanceof TypeError&&(j.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),j}}if(!h)return this.objectLength(f)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+"")},formatAndAdd:function(b,c){var d=this.defaultMessage(b,c.method),e=/\$?\{(\d+)\}/g;"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),this.errorList.push({message:d,element:b,method:c.method}),this.errorMap[b.name]=d,this.submitted[b.name]=d},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g=this.errorsFor(b),h=this.idOrName(b),i=a(b).attr("aria-describedby");g.length?(g.removeClass(this.settings.validClass).addClass(this.settings.errorClass),g.html(c)):(g=a("<"+this.settings.errorElement+">").attr("id",h+"-error").addClass(this.settings.errorClass).html(c||""),d=g,this.settings.wrapper&&(d=g.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement(d,a(b)):d.insertAfter(b),g.is("label")?g.attr("for",h):0===g.parents("label[for='"+h+"']").length&&(f=g.attr("id").replace(/(:|\.|\[|\]|\$)/g,"\\$1"),i?i.match(new RegExp("\\b"+f+"\\b"))||(i+=" "+f):i=f,a(b).attr("aria-describedby",i),e=this.groups[b.name],e&&a.each(this.groups,function(b,c){c===e&&a("[name='"+b+"']",this.currentForm).attr("aria-describedby",g.attr("id"))}))),!c&&this.settings.success&&(g.text(""),"string"==typeof this.settings.success?g.addClass(this.settings.success):this.settings.success(g,b)),this.toShow=this.toShow.add(g)},errorsFor:function(b){var c=this.idOrName(b),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+d.replace(/\s+/g,", #")),this.errors().filter(e)},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+b+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return this.dependTypes[typeof a]?this.dependTypes[typeof a](a,b):!0},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(a){this.pending[a.name]||(this.pendingRequest++,this.pending[a.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b){return a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,"remote")})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0!==e.param?e.param:!0:delete b[d]}}),a.each(b,function(d,e){b[d]=a.isFunction(e)?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},creditcard:function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||d>=e},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||c>=a},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.off(".validate-equalTo").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d){if(this.optional(c))return"dependency-mismatch";var e,f,g=this.previousValue(c);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),g.originalMessage=this.settings.messages[c.name].remote,this.settings.messages[c.name].remote=g.message,d="string"==typeof d&&{url:d}||d,g.old===b?g.valid:(g.old=b,e=this,this.startRequest(c),f={},f[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:f,context:e.currentForm,success:function(d){var f,h,i,j=d===!0||"true"===d;e.settings.messages[c.name].remote=g.originalMessage,j?(i=e.formSubmitted,e.prepareElement(c),e.formSubmitted=i,e.successList.push(c),delete e.invalid[c.name],e.showErrors()):(f={},h=d||e.defaultMessage(c,"remote"),f[c.name]=g.message=a.isFunction(h)?h(b):h,e.invalid[c.name]=!0,e.showErrors(f)),g.valid=j,e.stopRequest(c,j)}},d)),"pending")}}});var b,c={};a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)})}); -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /App/AttendeeList/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Damian Edwards 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 | 23 | -------------------------------------------------------------------------------- /Labs/1. Introduction to the .NET Core SDK.md: -------------------------------------------------------------------------------- 1 | # Introduction to the .NET Core SDK 2 | 3 | ## Install the .NET Core SDK 4 | 1. Go to https://dot.net and follow the instructions to download and install the .NET Core SDK for your OS 5 | 6 | ## Create and run your first application 7 | 1. Open a command prompt 8 | 1. Make a new directory to put your application in and change to it 9 | 10 | ``` 11 | mkdir MyNewApp 12 | cd MyNewApp 13 | ``` 14 | 1. Create a new application by typing `dotnet new` 15 | 1. Restore the application's dependencies by typing `dotnet restore` 16 | 1. Run the application by typing `dotnet run` 17 | 1. Open the `Program.cs` file and change the greeting message 18 | 1. Run the application again using `dotnet run` and note the message about the application being re-built 19 | 20 | ## Run the project output directly 21 | 1. `dotnet run` checks the project source every time to determine if a re-build is necessary and as such is intended for active development scenarios. 22 | 1. Run the project output directly by typing `dotnet ./bin/Debug/netcoreapp1.0/MyNewApp.dll` 23 | 1. Change the greeting in `Program.cs` again and run the application output directly once more, note that the greeting doesn't change as you didn't re-build the project. 24 | 1. Build the project by typing `dotnet build` 25 | 1. Run the project output directly again and see the greeting has now changed 26 | 27 | ## Explore the project files 28 | 1. Open the `project.json` file in Visual Studio and explore its contents and try using the IntelliSense to change some project configuration values 29 | 1. Look at the files and directories created when the project is built 30 | 31 | ## Make it a web application 32 | 1. Add a reference to the ASP.NET Core web server "Kestrel" by adding it to the `"dependencies"` section of the `project.json` file: 33 | 34 | ``` json 35 | { 36 | "dependencies": { 37 | "Microsoft.NETCore.App": { "version": "1.0.0-rc2-3002702", "type": "platform" }, 38 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final" 39 | } 40 | } 41 | ``` 42 | 1. At the command prompt, restore the new dependency by typing `dotnet restore` 43 | 1. Open the `Program.cs` file and add the following `using` statements to the top of the `Program.cs` file: 44 | 45 | ``` c# 46 | using Microsoft.AspNetCore.Builder; 47 | using Microsoft.AspNetCore.Http; 48 | using Microsoft.AspNetCore.Hosting; 49 | ``` 50 | 1. Change the `Main` method to: 51 | 52 | ``` c# 53 | public static void Main(string[] args) 54 | { 55 | var host = new WebHostBuilder() 56 | .UseKestrel() 57 | .Configure(app => app.Run(context => context.Response.WriteAsync("Hello World!"))) 58 | .Build(); 59 | 60 | host.Run(); 61 | } 62 | ``` 63 | 1. At the command prompt, run the application using `dotnet run` 64 | 1. Open a web browser and browse to http://localhost:5000/ to see the greeting 65 | -------------------------------------------------------------------------------- /Labs/2. Introduction to ASP.NET Core.md: -------------------------------------------------------------------------------- 1 | 2 | ## Create a new ASP.NET Core application 3 | 4 | 1. Open Visual Studio 2015 Update 2 5 | 1. Create a new ASP.NET Core application: 6 | 1. File -> New -> Project -> C# -> .NET Core -> ASP.NET Core Web Application (.NET Core) (Empty Template) 7 | 8 | ## Running the application under IIS 9 | 10 | 1. The application should be setup to run under IIS by default. 11 | 1. Run the application and navigate to the root. It should show the hello world middleware. 12 | 13 | ## Running the application on Kestrel directly 14 | 15 | 1. Change the Debug drop down in the toolbar to the application name as shown below. 16 | 17 | ![image](https://cloud.githubusercontent.com/assets/95136/15806049/abf005b6-2b3a-11e6-8fb4-ca75c9f68913.png) 18 | 19 | 1. Run the application and navigate to the root. It should show the hello world middleware. 20 | 1. Change the port to `8081` by adding a call to `UseUrls` in the `Startup.cs`: 21 | 22 | ``` 23 | public class Program 24 | { 25 | public static void Main(string[] args) 26 | { 27 | var host = new WebHostBuilder() 28 | .UseKestrel() 29 | .UseUrls("http://localhost:8081") 30 | .UseContentRoot(Directory.GetCurrentDirectory()) 31 | .UseIISIntegration() 32 | .UseStartup() 33 | .Build(); 34 | host.Run(); 35 | 36 | } 37 | } 38 | ``` 39 | 1. Navigate to the project properties (by right clicking on the project, and selection `Properties`) 40 | 1. Go to the `Debug` tab and change `Launch URL` to `http://localhost:8081` 41 | 42 | ![image](https://cloud.githubusercontent.com/assets/95136/15806095/157c4c32-2b3c-11e6-91db-b231aa113c31.png) 43 | 44 | 1. Run the application and navigate to the root. It should show the hello world middleware running on port 8081. 45 | 46 | ## Serving static files 47 | 48 | 1. Add the `Microsoft.AspNetCore.StaticFiles` package to `project.json`: 49 | 50 | ```JSON 51 | "dependencies": { 52 | "Microsoft.NETCore.App": { 53 | "version": "1.0.0-rc2-3002702", 54 | "type": "platform" 55 | }, 56 | "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final", 57 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 58 | "Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final" 59 | }, 60 | ``` 61 | 62 | 1. Save `project.json`. The NuGet package will be restored immediately. 63 | 64 | 1. Go to `Startup.cs` in the `Configure` method and add `UseStaticFiles` before the hello world middleware: 65 | 66 | ```C# 67 | public void Configure(IApplicationBuilder app) 68 | { 69 | app.UseStaticFiles(); 70 | 71 | app.Run(async context => 72 | { 73 | await context.Response.WriteAsync("Hello World"); 74 | }); 75 | } 76 | ``` 77 | 78 | 1. Create a folder called `wwwroot` in the project folder. 79 | 1. Create a file called `index.html` with the following contents in the `wwwroot` folder: 80 | 81 | ``` 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |

    Hello from ASP.NET Core!

    90 | 91 | 92 | ``` 93 | 94 | 1. Run the application and navigate to the root. It should show the hello world middleware. 95 | 1. Navigate to `index.html` and it should show the static page in `wwwroot`. 96 | 97 | ## Adding default document support 98 | 99 | 1. Change the static files middleware in `Startup.cs` from `app.UseStaticFiles()` to `app.UseFileServer()`. 100 | 1. Run the application. The default page `index.html` should show when navigating to the root of the site. 101 | 102 | ## Changing environments 103 | 104 | 1. The default environment in visual studio is development. In the property pages you can see this is specified by the environment variables section: 105 | 106 | ![image](https://cloud.githubusercontent.com/assets/95136/15806164/a57a79a2-2b3d-11e6-9551-9e106036e0c0.png) 107 | 108 | 1. Add some code to the `Configure` method in `Startup.cs` to take in `IHostingEnvironment` and print out the environment name. Make sure you comment out the UseFileServer middleware. Otherwise you'll still get the same default static page. 109 | 110 | ```C# 111 | public void Configure(IApplicationBuilder app, IHostingEnvironment environment) 112 | { 113 | //app.UseFileServer(); 114 | 115 | app.Run(async (context) => 116 | { 117 | await context.Response.WriteAsync($"Hello World! {environment.EnvironmentName}"); 118 | }); 119 | } 120 | ``` 121 | 1. Run the application and it should print out `Hello World! Development`. 122 | 1. Change the application to run in the `Production` environment by changing the `ASPNETCORE_ENVIRONMENT` environment variable on the `Debug` property page: 123 | 124 | ![image](https://cloud.githubusercontent.com/assets/95136/15806196/9b52efee-2b3e-11e6-851b-35765d5b2a4d.png) 125 | 126 | 1. Run the application and it should print out `Hello World! Production`. 127 | 128 | ## Setup the configuration system 129 | 130 | 1. Add the `Microsoft.Extensions.Configuration.Json` package to `project.json`: 131 | 132 | ```JSON 133 | "dependencies": { 134 | "Microsoft.NETCore.App": { 135 | "version": "1.0.0-rc2-3002702", 136 | "type": "platform" 137 | }, 138 | "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final", 139 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 140 | "Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final", 141 | "Microsoft.Extensions.Configuration.Json": "1.0.0-rc2-final" 142 | }, 143 | ``` 144 | 1. Add a `Configuration` property to `Startup.cs` of type `IConfigurationRoot`: 145 | 146 | ```C# 147 | public class Startup 148 | { 149 | ... 150 | public IConfigurationRoot Configuration { get; set; } 151 | ... 152 | } 153 | ``` 154 | 155 | 1. Go to `Startup.cs` and add a constructor that configures the configuration system: 156 | 157 | ```C# 158 | public Startup() 159 | { 160 | Configuration = new ConfigurationBuilder() 161 | .AddJsonFile("appsettings.json") 162 | .Build(); 163 | } 164 | ``` 165 | 1. Run the application and it should fail with an exception saying that it cannot find the `'appsettings.json'`. 166 | 1. Create a file in the root of the project called `appsettings.json` with the following content: 167 | 168 | ```JSON 169 | { 170 | "message": "Hello from configuration" 171 | } 172 | ``` 173 | 174 | 1. Modify the `Startup` constructor in `Startup.cs` to inject `IHostingEnvironment` and use it to set the base path for the configuration system to the `ContentRootPath`: 175 | 176 | ```C# 177 | public Startup(IHostingEnvironment env) 178 | { 179 | Configuration = new ConfigurationBuilder() 180 | .SetBasePath(env.ContentRootPath) 181 | .AddJsonFile("appsettings.json") 182 | .Build(); 183 | } 184 | ``` 185 | 186 | 1. In `Startup.cs` modify the `Configure` method to print out the configuration key in the http response: 187 | 188 | ```C# 189 | public void Configure(IApplicationBuilder app, IHostingEnvironment environment) 190 | { 191 | app.UseStaticFiles(); 192 | 193 | app.Run(async (context) => 194 | { 195 | await context.Response.WriteAsync($"{Configuration["message"]}"); 196 | }); 197 | } 198 | ``` 199 | 200 | 1. Run the application and it should print out `Hello from config`. 201 | 202 | ## Extra 203 | - Add support for reloading the configuration without an application restart. 204 | - Replace the JSON configuration provider with the XML configuration provider 205 | - Write a custom configuration provider 206 | -------------------------------------------------------------------------------- /Labs/3. Introduction to Routing & MVC.md: -------------------------------------------------------------------------------- 1 | # Introduction to Routing & MVC 2 | 3 | ## Install the routing package 4 | 1. Use the application you created in the earlier labs 5 | 1. Open the `project.json` file 6 | 1. In the `dependencies` section, add an entry for the "Microsoft.AspNetCore.Routing" package: 7 | 8 | ``` JSON 9 | "dependencies": { 10 | ..., 11 | "Microsoft.AspNetCore.Routing": "1.0.0-rc2-final" 12 | } 13 | ``` 14 | 1. Save the file. Open the `Startup.cs` file 15 | 1. Add the routing services to the configuration in the `Startup.cs`: 16 | 17 | ``` c# 18 | public void ConfigureServices(IServiceCollection services) 19 | { 20 | services.AddRouting(); 21 | } 22 | ``` 23 | 1. In the `Configure` method, create a `RouteBuilder` with a handler for the root of the site and add it to the middleware pipeline: 24 | 25 | ``` c# 26 | using Microsoft.AspNetCore.Routing; 27 | ... 28 | public void Configure(IApplicationBuilder app) 29 | { 30 | var routeBuilder = new RouteBuilder(app); 31 | 32 | routeBuilder.MapGet("", context => context.Response.WriteAsync("Hello from Routing!")); 33 | 34 | app.UseRouter(routeBuilder.Build()); 35 | } 36 | ``` 37 | 1. Run the site and verify your middleware is hit via routing (Ctrl+F5) 38 | 1. Add another route that matches a sub-path: 39 | 40 | ``` c# 41 | routeBuilder.MapGet("sub", context => context.Response.WriteAsync("Hello from sub!")); 42 | ``` 43 | 1. Run the site and verify that your routes are hit when the matching URL is browsed to 44 | 45 | ## Capture and use route data 46 | 1. Add another route that captures the name of an item from the URL, e.g. "item/{itemName}", and displays it in the response: 47 | 48 | ``` c# 49 | routeBuilder.MapGet("item/{itemName}", context => context.Response.WriteAsync($"Item: {context.GetRouteValue("itemName")}")); 50 | ``` 51 | 1. Run the site and verify that your new route works 52 | 1. Modify the route to include a route constraint on the captured segmet, enforcing it to be a number: 53 | 54 | ``` c# 55 | routeBuilder.MapGet("item/{id:int}", context => context.Response.WriteAsync($"Item ID: {context.GetRouteValue("id")}")); 56 | ``` 57 | 1. Run the site again and see that the route is only matched when the captured segment is a valid number 58 | 1. Modify the router to include both versions of the route above (with and without the route constraint) 59 | 1. Experiment with changing the order the routes are added and observe what affect that has on which route is matched for a given URL 60 | 61 | # Add MVC 62 | 1. Open `project.json` and add "Microsoft.AspNetCore.Mvc" to the `"dependencies"` section and save it: 63 | 64 | ``` JSON 65 | "dependencies": { 66 | ..., 67 | "Microsoft.AspNetCore.Mvc": "1.0.0-*" 68 | } 69 | ``` 70 | 1. Add a "Controllers" folder to your application 71 | 1. Create a new controller called "HomeController" in the new folder: 72 | 73 | ``` c# 74 | public class HomeController 75 | { 76 | [HttpGet("/")] 77 | public string Index() => "Hello from MVC!"; 78 | } 79 | ``` 80 | 1. Add the MVC services and middleware to the configuration in the `Startup.cs`: 81 | 82 | ``` c# 83 | public void ConfigureServices(IServiceCollection services) 84 | { 85 | services.AddMvc(); 86 | } 87 | 88 | public void Configure(IApplicationBuilder app) 89 | { 90 | ... 91 | app.UseMvc(); 92 | } 93 | ``` 94 | 1. Run the site and verify the message is returned from your MVC controller 95 | 1. If you have time, try the following: 96 | - Change the controller to render a view instead of returning a string directly 97 | - Play with the `[HttpGet("/")]` attribute to change the route the action method will match 98 | -------------------------------------------------------------------------------- /Labs/4. Logging and Diagnostics.md: -------------------------------------------------------------------------------- 1 | ## Logging 2 | 3 | ## Setting up your application for logging 4 | 1. Use the application from the [Lab 2](2. Introduction to ASP.NET Core.md) (or setup steps from the Lab 2). 5 | 2. Add the `Microsoft.Extensions.Logging.Console` package to `project.json` and save your changes: 6 | 7 | ```JSON 8 | "dependencies": { 9 | "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final" 10 | }, 11 | ``` 12 | 3. Navigate to `Startup.cs` and change the `Configure` method to: 13 | 14 | ```C# 15 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 16 | { 17 | loggerFactory.AddConsole(); 18 | 19 | var startupLogger = loggerFactory.CreateLogger(); 20 | ... 21 | } 22 | ``` 23 | 24 | 4. Add a log statement to the end of the `Configure` method: 25 | 26 | ```C# 27 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 28 | { 29 | ... 30 | startupLogger.LogInformation("Application startup complete!"); 31 | } 32 | ``` 33 | 34 | 5. In Visual Studio, change the active launch host to the application itself (self-host) by navigating to the play/run button and changing the drop-down to the entry named after the application. 35 | 36 | ![image](https://cloud.githubusercontent.com/assets/95136/12222924/633ef134-b7c1-11e5-9146-da36013da8d8.png) 37 | 38 | 6. Run the application and open a browser window with `http://localhost:5000/` as the address. You should see the default log messages from the framework as well as your custom log message in the console window. 39 | 40 | ## Filtering logs 41 | 1. Add a couple more logging statements to the `Configure` method: 42 | 43 | ```C# 44 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 45 | { 46 | ... 47 | startupLogger.LogInformation("Application startup complete!"); 48 | 49 | startupLogger.LogCritical("This is a critical message"); 50 | startupLogger.LogDebug("This is a debug message"); 51 | startupLogger.LogTrace("This is a trace message"); 52 | startupLogger.LogWarning("This is a warning message"); 53 | startupLogger.LogError("This is an error message"); 54 | } 55 | ``` 56 | 57 | 2. Change the minimum log level for the console logger in `Startup.cs`: 58 | 59 | ```C# 60 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 61 | { 62 | loggerFactory.AddConsole(LogLevel.Trace); 63 | ... 64 | } 65 | ``` 66 | 67 | 3. Run the application and open a browser window with `http://localhost:5000/` as the address. You should see more verbose logging from the framework and startup including debug messages. 68 | 69 | 4. Change the application to only show logs from the Startup category: 70 | 71 | ```C# 72 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 73 | { 74 | loggerFactory.AddConsole((category, level) => category == typeof(Startup).FullName); 75 | ... 76 | } 77 | ``` 78 | 79 | 5. Run the application and open a browser window with `http://localhost:5000/` as the address. You should only logs written by the Startup logger. 80 | 81 | ## Adding other logging providers 82 | 1. Add the Serilog logger provider to `project.json`: 83 | 84 | ```JSON 85 | "dependencies": { 86 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 87 | "Microsoft.AspNetCore.Logging.Console": "1.0.0-rc2-final", 88 | "Serilog.Extensions.Logging": "1.0.0-rc2-10110", 89 | "Serilog.Sinks.File": "2.0.0-rc-706" 90 | }, 91 | ``` 92 | 2. Configure the Serilog in `Startup.cs` to write to a file called `logfile.txt` in the project root: 93 | 94 | ```C# 95 | public class Startup 96 | { 97 | public Startup(IHostingEnvironment hostingEnvironment) 98 | { 99 | var logFile = Path.Combine(hostingEnvironment.ContentRootPath, "logfile.txt"); 100 | 101 | Log.Logger = new LoggerConfiguration() 102 | .WriteTo.File(logFile) 103 | .CreateLogger(); 104 | } 105 | } 106 | ``` 107 | 3. Add the Serilog provider in `Configure`: 108 | 109 | ```C# 110 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 111 | { 112 | loggerFactory.AddConsole(); 113 | loggerFactory.AddSerilog(); 114 | ... 115 | } 116 | ``` 117 | 118 | 4. Run the application and open a browser window with `http://localhost:5000/` as the address. You should only a file called `logfile.txt` appear in your application root. 119 | 120 | 5. Closing the conosle window and open the file, the application logs should be in there. 121 | 122 | ## Extra 123 | 1. Try adding more advanced filters with different levels. 124 | 2. Try configuring logging using the Configuration system (`IConfiguration`). 125 | 126 | # Diagnostic pages 127 | 128 | ## Write some buggy code 129 | 130 | 1. Add a middleware to the above application that throws an exception. Your `Configure` method should look something like this: 131 | 132 | ```C# 133 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 134 | { 135 | loggerFactory.AddConsole(); 136 | 137 | loggerFactory.AddSerilog(); 138 | 139 | ... 140 | 141 | app.Run((context) => 142 | { 143 | throw new InvalidOperationException("Oops!"); 144 | }); 145 | 146 | ... 147 | } 148 | ``` 149 | 2. Run the application and open a browser window with `http://localhost:5000/` as the address. The debugger will break at the ` `InvalidOperationException`. If you type `F5` again to continue, you should see a generic browser error page but the exception message should appear in the console. 150 | 151 | ## Adding the diagnostics middleware 152 | 153 | 1. Add the `Microsoft.AspNetCore.Diagnostics` to `project.json`: 154 | 155 | ```JSON 156 | "dependencies": { 157 | "Microsoft.AspNetCore.Diagnostics": "1.0.0-rc2-final", 158 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 159 | "Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final", 160 | "Serilog.Extensions.Logging": "1.0.0-rc2-10110", 161 | "Serilog.Sinks.File": "2.0.0-rc-706" 162 | }, 163 | ``` 164 | 165 | 2. Add the developer experience middleware before the middleware that throws the exception: 166 | 167 | ```C# 168 | app.UseDeveloperExceptionPage(); 169 | 170 | app.Run((context) => 171 | { 172 | throw new InvalidOperationException("Oops!"); 173 | }); 174 | ``` 175 | 3. Run the application and open a browser window with `http://localhost:5000/` as the address. The debugger will break at the ` `InvalidOperationException`. If you type `F5` again to continue, you should see an application exception page in the browser. 176 | 177 | ## Only showing exception pages during development 178 | 179 | 1. Change the Configure method signature to take `IHostingEnvironment`: 180 | 181 | ```C# 182 | public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IHostingEnvironment env) 183 | ``` 184 | 185 | 2. Add the exception handler middleware to the `Configure` method. Make sure it only runs when not in development: 186 | 187 | ```C# 188 | if (env.IsDevelopment()) 189 | { 190 | app.UseDeveloperExceptionPage(); 191 | } 192 | else 193 | { 194 | app.UseExceptionHandler(subApp => 195 | { 196 | subApp.Run(async context => 197 | { 198 | context.Response.ContentType = "text/html"; 199 | await context.Response.WriteAsync(" Oops! Something went wrong :( "); 200 | await context.Response.WriteAsync(new string(' ', 512)); // Padding for IE 201 | }); 202 | }); 203 | } 204 | ``` 205 | 206 | 3. Run the application in "Production" and open a browser window with `http://localhost:5000/` as the address. Type `F5` at the exception and you should see the custom error page instead of the exception. 207 | 208 | ## Showing custom pages for non 500 status codes 209 | 210 | 1. Change the middleware throwing the exception message to instead set a 404 status code: 211 | 212 | ```C# 213 | app.Run((context) => 214 | { 215 | context.Response.StatusCode = 404; 216 | return Task.FromResult(0); 217 | }); 218 | ``` 219 | 2. Add the status code pages middleware above the exception handler middleware in `Configure`: 220 | 221 | ```C# 222 | app.UseStatusCodePages(subApp => 223 | { 224 | subApp.Run(async context => 225 | { 226 | context.Response.ContentType = "text/html"; 227 | await context.Response.WriteAsync($" You got a {context.Response.StatusCode}"); 228 | await context.Response.WriteAsync(new string(' ', 512)); // Padding for IE 229 | }); 230 | }); 231 | 232 | ... 233 | ``` 234 | 3. Run the application and open a browser window with `http://localhost:5000/` as the address. You should see the custom error page instead of the browser's default 404 page. 235 | 236 | ## Extra 237 | 1. Access the exception when using the exception handler middleware, log it to the logging system. (**Note: The exception handler middleware does log the exception via the logging system.**) 238 | 2. Serve an html page when an exception occurs using the static files middleware and the exception handler middleware. 239 | 3. Serve an html page for a 404 status using the static files middleware and status code pages middleware. 240 | 4. Write a custom logging provider 241 | -------------------------------------------------------------------------------- /Labs/4.5 Building Middleware.md: -------------------------------------------------------------------------------- 1 | 2 | # Building middleware 3 | 4 | ## Write a middleware that sets the current culture based on a query string value 5 | 1. Start with the application you created in [Lab 2](2. Introduction to ASP.NET Core.md), or just create a new empty ASP.NET 5 application 6 | 1. Open `Startup.cs` 7 | 1. Create an inline middleware that runs **before** the hello world delegate that sets the culture for the current request from the query string: 8 | 9 | ``` C# 10 | public void Configure(IApplicationBuilder app) 11 | { 12 | app.Use((context, next) => 13 | { 14 | var cultureQuery = context.Request.Query["culture"]; 15 | if (!string.IsNullOrWhiteSpace(cultureQuery)) 16 | { 17 | var culture = new CultureInfo(cultureQuery); 18 | 19 | CultureInfo.CurrentCulture = culture; 20 | CultureInfo.CurrentUICulture = culture; 21 | } 22 | 23 | // Call the next delegate/middleware in the pipeline 24 | return next(); 25 | }); 26 | 27 | app.Run(async (context) => 28 | { 29 | await context.Response.WriteAsync($"Hello {CultureInfo.CurrentCulture.DisplayName}"); 30 | }); 31 | } 32 | ``` 33 | 34 | 1. Run the app now and set the culture via the query string, e.g. http://localhost/?culture=no 35 | 36 | 37 | ## Move the middleware to its own type 38 | 1. Create a new class in the application `RequestCultureMiddleware` 39 | 1. Add a constructor that takes a parameter `RequestDelegate next` and assigns it to a private field `private readonly RequestDelegate _next` 40 | 1. Add a method `public Task Invoke(HttpContext context)` 41 | 1. Copy the code from the inline middleware delegate in the application's `Startup.cs` file to the `Invoke` method you just created and fix the `next` method name 42 | 1. Your middleware class should now look something like this: 43 | 44 | ``` C# 45 | public class RequestCultureMiddleware 46 | { 47 | private readonly RequestDelegate _next; 48 | 49 | public RequestCultureMiddleware(RequestDelegate next) 50 | { 51 | _next = next; 52 | } 53 | 54 | public Task Invoke(HttpContext context) 55 | { 56 | var cultureQuery = context.Request.Query["culture"]; 57 | if (!string.IsNullOrWhiteSpace(cultureQuery)) 58 | { 59 | var culture = new CultureInfo(cultureQuery); 60 | 61 | CultureInfo.CurrentCulture = culture; 62 | CultureInfo.CurrentUICulture = culture; 63 | } 64 | 65 | return _next(context); 66 | } 67 | } 68 | ``` 69 | 70 | 1. At the bottom of the file, add a class that exposes the middleware via an extension method on `IApplicationBuilder`. 71 | 72 | ```C# 73 | public static class RequestCultureMiddlewareExtensions 74 | { 75 | public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder) 76 | { 77 | return builder.UseMiddleware(); 78 | } 79 | } 80 | ``` 81 | 82 | 1. Back in the application's `Startup.cs` file, delete the inline middleware delegate 83 | 1. Add your new middleware class to the HTTP pipeline: 84 | 85 | ``` C# 86 | app.UseRequestCulture(); 87 | ``` 88 | 89 | 1. Run the application again and see that the middleware is now running as a class 90 | 91 | ## Adding options to middleware 92 | 1. Create a class called `RequestCultureOptions.cs` with a `CultureInfo` property called DefaultCulture. 93 | 94 | ```C# 95 | public class RequestCultureOptions 96 | { 97 | public CultureInfo DefaultCulture { get; set; } 98 | } 99 | ``` 100 | 1. Add an overload to `UseRequestCulture` that takes those options and passes them into the `UseMiddleware` call. 101 | 102 | ```C# 103 | public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder) 104 | { 105 | return builder.UseRequestCulture(new RequestCultureOptions()); 106 | } 107 | 108 | public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder, RequestCultureOptions options) 109 | { 110 | return builder.UseMiddleware(options); 111 | } 112 | ``` 113 | 1. Change the `RequestCultureMiddleware` constructor to take the `RequestCultureOptions`. 114 | 115 | ```C# 116 | public class RequestCultureMiddleware 117 | { 118 | private readonly RequestDelegate _next; 119 | private readonly RequestCultureOptions _options; 120 | 121 | public RequestCultureMiddleware(RequestDelegate next, RequestCultureOptions options) 122 | { 123 | _next = next; 124 | _options = options; 125 | } 126 | ... 127 | } 128 | ``` 129 | 130 | 1. Change the `Invoke` method of the middleware to use the DefaultCulture from options if none specified on the query string 131 | 132 | ```C# 133 | public Task Invoke(HttpContext httpContext) 134 | { 135 | CultureInfo requestCulture = null; 136 | 137 | var cultureQuery = httpContext.Request.Query["culture"]; 138 | if (!string.IsNullOrWhiteSpace(cultureQuery)) 139 | { 140 | requestCulture = new CultureInfo(cultureQuery); 141 | } 142 | else 143 | { 144 | requestCulture = _options.DefaultCulture; 145 | } 146 | 147 | if (requestCulture != null) 148 | { 149 | CultureInfo.CurrentCulture = requestCulture; 150 | CultureInfo.CurrentUICulture = requestCulture; 151 | } 152 | 153 | return _next(httpContext); 154 | } 155 | ``` 156 | 1. Set the fallback culture in `Startup.cs` `Configure` method to some default value: 157 | 158 | ```C# 159 | app.UseRequestCulture(new RequestCultureOptions 160 | { 161 | DefaultCulture = new CultureInfo("en-GB") 162 | }); 163 | ``` 164 | 165 | 1. Run the application again and see the default culture when no query string is specified matches the one configured. 166 | 167 | ## Read request culture configuration from a file 168 | 1. Add a constructor to the application's `Startup.cs` 169 | 1. Create a new `Configuration` object in the constructor and assign it to a new private class field `IConfiguration _configuration` 170 | 1. Add a reference to the `Microsoft.Extensions.Configuration.Json` package in the application's `project.json` file 171 | 1. Back in the `Startup.cs`, add a call to `.AddJsonFile("config.json")` immediately after the creation of the `Configuration` object (inline, chained method). It should now look like the following: 172 | 173 | ``` C# 174 | public class Startup 175 | { 176 | private readonly IConfiguration _configuration; 177 | 178 | public Startup() 179 | { 180 | var configuration = new ConfigurationBuilder() 181 | .AddJsonFile("config.json") 182 | .Build(); 183 | 184 | _configuration = configuration; 185 | } 186 | ... 187 | } 188 | ``` 189 | 190 | 1. Add a new JSON file to the project called `config.json` 191 | 1. Add a new key/value pair to the `config.json` file: `"culture": "en-US"` 192 | 1. Change the code in `Startup.cs` to set the default culture using the configuration system: 193 | 194 | ``` C# 195 | app.UseRequestCulture(new RequestCultureOptions 196 | { 197 | DefaultCulture = new CultureInfo(_configuration["culture"] ?? "en-GB") 198 | }); 199 | ``` 200 | 201 | 1. Run the application and the default culture should be set from the configuration file. 202 | 1. Change the culture in the `config.json` file and refresh the page (without changing any other code). Note that the message hasn't changed as the configuration was only read when the application was started. 203 | 1. Go back to Visual Studio and touch and save the `Startup.cs` file to force the process to restart 204 | 1. Go back to the browser now and refresh the page and it should show the updated message 205 | 206 | 207 | ## Flowing options from dependency injection system to middleware 208 | 209 | 1. Add the `Microsoft.Extensions.Options` package to `project.json`. 210 | 211 | 1. Change the `RequestCultureMiddleware` constructor to take `IOptions` instead of `RequestCultureOptions`: 212 | 213 | ```C# 214 | public RequestCultureMiddleware(RequestDelegate next, IOptions options) 215 | { 216 | _next = next; 217 | _options = options.Value; 218 | } 219 | ``` 220 | 221 | 1. Change the `UseRequestCulture` extension methods to both call `UseMiddleware`. The overload taking `RequestCultureOptions` should wrap it in an `IOptions` by calling `Options.Create(options)`: 222 | 223 | ```C# 224 | public static class RequestCultureMiddlewareExtensions 225 | { 226 | public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder) 227 | { 228 | return builder.UseMiddleware(); 229 | } 230 | 231 | public static IApplicationBuilder UseRequestCulture(this IApplicationBuilder builder, RequestCultureOptions options) 232 | { 233 | return builder.UseMiddleware(Options.Create(options)); 234 | } 235 | } 236 | ``` 237 | 1. In `Startup.cs` change the `UseRequestCulture` middleware to not take any arguments: 238 | 239 | ```C# 240 | app.UseRequestCulture(); 241 | ``` 242 | 243 | 1. In `Startup.cs` add a `ConfigureServices(ISeviceCollection services)` method and add a line that configures the culture using the `services.Configure` method: 244 | 245 | ```C# 246 | public void ConfigureServices(IServiceCollection services) 247 | { 248 | services.Configure(options => 249 | { 250 | options.DefaultCulture = new CultureInfo(_configuration["culture"] ?? "en-GB"); 251 | }); 252 | } 253 | ``` 254 | 255 | 1. Run the application and see that options are now being configured from the dependency injection system. 256 | -------------------------------------------------------------------------------- /Labs/5. Dependency Injection & Unit Testing.md: -------------------------------------------------------------------------------- 1 | # Using Dependency Injection (DI) to register and resolve application services 2 | 3 | ## Creating a service to assign request IDs 4 | 1. Create a folder in the application called `Services` 5 | 1. Create a new class file in the `Services` folder `RequestId` 6 | 1. In the file, create an interface `IRequestIdFactory` with a single method `string MakeRequestId()` 7 | 1. In the same file, create a class `RequestIdFactory` that implements `IRequestIdFactory` by using `Interlock.Increment` to make an increasing request ID 8 | 1. The file should look something like this: 9 | 10 | ``` C# 11 | public interface IRequestIdFactory 12 | { 13 | string MakeRequestId(); 14 | } 15 | 16 | public class RequestIdFactory : IRequestIdFactory 17 | { 18 | private int _requestId; 19 | 20 | public string MakeRequestId() => Interlocked.Increment(ref _requestId).ToString(); 21 | } 22 | ``` 23 | 24 | 1. In the same file, create an interface `IRequestId` with a single property `string Id { get; }` 25 | 1. In the same file, create a class `RequestId` that implements `IRequestId` by taking an `IRequestIdFactory` in the constructor and calling its `MakeRequestId` method to get a new ID. 26 | 1. The whole file should now look something like this: 27 | 28 | ``` C# 29 | public interface IRequestIdFactory 30 | { 31 | string MakeRequestId(); 32 | } 33 | 34 | public class RequestIdFactory : IRequestIdFactory 35 | { 36 | private int _requestId; 37 | 38 | public string MakeRequestId() => Interlocked.Increment(ref _requestId).ToString(); 39 | } 40 | 41 | public interface IRequestId 42 | { 43 | string Id { get; } 44 | } 45 | 46 | public class RequestId : IRequestId 47 | { 48 | private readonly string _requestId; 49 | 50 | public RequestId(IRequestIdFactory requestIdFactory) 51 | { 52 | _requestId = requestIdFactory.MakeRequestId(); 53 | } 54 | 55 | public string Id => _requestId; 56 | } 57 | ``` 58 | 59 | ## Register the request ID service in DI 60 | 1. In the application's `Startup.cs` file, add a method `public void ConfigureServices(IServiceCollection services)` 61 | 1. Register the `IRequestIdFactory` service as a singleton: `services.AddSingleton();` 62 | 1. Register the `IRequestId` service as scoped: `services.AddScoped();` 63 | 1 The `ConfigureServices` method should now look something like this: 64 | 65 | ``` C# 66 | public void ConfigureServices(IServiceCollection services) 67 | { 68 | services.AddSingleton(); 69 | services.AddScoped(); 70 | } 71 | ``` 72 | 73 | ## Create and add a middleware that logs the request ID 74 | 1. Create a new folder in the application `Middleware` 75 | 1. In the folder, create a class `RequestIdMiddleware` 76 | 1. Create a constructor `public RequestIdMiddleware(RequestDelegate next, IRequestId requestId, ILogger logger)` and store the parameters in private fields 77 | 1. Add a method `public Task Invoke(HttpContext context)` and in its body log the request ID using the `ILogger` and `IRequestId` injected from the constructor 78 | 1. Your middleware class should look something like this: 79 | 80 | ``` C# 81 | public class RequestIdMiddleware 82 | { 83 | private readonly RequestDelegate _next; 84 | private readonly ILogger _logger; 85 | 86 | public RequestIdMiddleware(RequestDelegate next, IRequestId requestId, ILogger logger) 87 | { 88 | _next = next; 89 | _logger = logger; 90 | } 91 | 92 | public Task Invoke(HttpContext context, IRequestId requestId) 93 | { 94 | _logger.LogInformation($"Request {requestId.Id} executing."); 95 | 96 | return _next(context); 97 | } 98 | } 99 | ``` 100 | 101 | 1. Add the middleware to your pipeline back in `Startup.cs` by calling `app.UseMiddleware();` 102 | 103 | ## Configure a logger so you can see the request ID messages 104 | 1. In the `project.json` file, add the dependency `Microsoft.Extensions.Logging.Debug`. 105 | 1. In the `Startup.cs` file, add a parameter to the `Configure` method: `ILoggerFactory loggerFactory` 106 | 1. Add the `DebugLoggerProvider` at the beginning of the method body: `loggerFactory.AddDebug();` 107 | 1. Debug the application (F5) and you should see the messages containing the request ID being logged into the debug output 108 | 109 | # Adding a unit test project 110 | 111 | Follow the instructions at https://xunit.github.io/docs/getting-started-dotnet-core.html to add an xUnit testing project. 112 | -------------------------------------------------------------------------------- /Labs/6. Working with Razor Tag Helpers.md: -------------------------------------------------------------------------------- 1 | # Working with Razor Tag Helpers 2 | 3 | ## Look at Tag Helpers in the project template 4 | 1. Create a new ASP.NET Core project using the "Web Application" template 5 | 1. Open the view `Views/Account/Register.cshtml` 6 | 1. Look at the Tag Helpers being used in this view (they're colored purple and in bold, make sure you build the project) and play around with setting their attributes and exploring the IntelliSense offered for the different attribute types 7 | 1. Run the application and see the HTML output by the Tag Helpers 8 | 1. Look at the other views in `Views/Account/` folder to see how they use Tag Helpers 9 | 1. Open the file `Views/Shared/_Layout.cshtml` 10 | 1. Look at the Tag Helpers being used in the `` element and at the end of the page to render CSS stylesheets and JavaScript files and compare it to the generated HTML output 11 | 12 | ## Create a custom Tag Helper 13 | 1. Create a new class in the application you created above, `public class RepeatTagHelper : TagHelper` and resolve any required namespaces 14 | 1. Add a property `public int Count { get; set; }` 15 | 1. Override the `ProcessAsync(TagHelperContext context, TagHelperOutput output)` method 16 | 1. Replace the body of `ProcessAsync` with the code below, which repeats the content via the `output` parameter in a loop for `Count` iterations, e.g.: 17 | 18 | ``` C# 19 | for (int i = 0; i < Count; i++) 20 | { 21 | output.Content.AppendHtml(await output.GetChildContentAsync(useCachedResult: false)); 22 | } 23 | ``` 24 | 25 | 1. Open the `_ViewImports.cshtml` file and add line to register your Tag Helper: `@addTagHelper "*, WebApplication49"` (adjust WebApplication49 to your assembly name) 26 | 1. Open `Views/Home/Index.cshtml` and use your Tag Helper, e.g.: 27 | 28 | ``` HTML 29 | 30 |

    I'll be repeated!! @DateTime.UtcNow.Ticks

    31 |
    32 | ``` 33 | 34 | 1. Run the application again and ensure your Tag Helper is working 35 | 1. Note that the Tag Helper is rendering itself as a `` tag (see it in the rendered HTML). We'll fix that now so that only the contents are rendered. 36 | 1. Open the `RepeatTagHelper` again and in the `ProcessAsync` method add a line to null out the tag name: `output.TagName = null;` 37 | 1. Run the application again and see that the outer tag is no longer rendered 38 | 39 | ## Extra if you have time 40 | 1. Experiment with decorating your `RepeatTagHelper` class with the `[HtmlTargetElement()]` attribute to change which HTML tag and/or attribute names it will attach itself to 41 | -------------------------------------------------------------------------------- /Labs/7. APIs with MVC Core.md: -------------------------------------------------------------------------------- 1 | # Build a simple API 2 | 3 | ## Prerequisites 4 | 5 | - Download [POSTman](https://www.getpostman.com/) OR [Fiddler](http://www.telerik.com/fiddler) 6 | 7 | ## Setting up the MVC API project 8 | 9 | 1. Use the instructions in Getting Started to setup an Empty Web Application. 10 | 2. Add `Microsoft.AspNetCore.Mvc.Core` to `project.json`: 11 | 12 | ```JSON 13 | "dependencies": { 14 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 15 | "Microsoft.AspNetCore.Mvc.Core": "1.0.0-rc2-final", 16 | }, 17 | ``` 18 | 3. In `Startup.cs` add `services.AddMvcCore()` to `ConfigureServices` and add `app.UseMvc()` to `Configure`: 19 | 20 | ```C# 21 | public void ConfigureServices(IServiceCollection services) 22 | { 23 | services.AddMvcCore(); 24 | } 25 | 26 | public void Configure(IApplicationBuilder app) 27 | { 28 | app.UseMvc(); 29 | } 30 | ``` 31 | 32 | 4. Create a folder called `Models` and create a class called `Product` in that folder: 33 | 34 | ```C# 35 | public class Product 36 | { 37 | public int Id { get; set; } 38 | public string Name { get; set; } 39 | } 40 | ``` 41 | 42 | 5. Create a folder called `Controllers` and create a class called `ProductsController` in that folder. 43 | 6. Add an attribute route `[Route("/api/[controller]")]` to the `ProductsController` class: 44 | 45 | ```C# 46 | [Route("/api/[controller]")] 47 | public class ProductsController 48 | { 49 | } 50 | ``` 51 | 52 | 7. Add a `Get` method to `ProductsController` that returns a `string` "Hello API World" with an attribute route 53 | 54 | ```C# 55 | [Route("/api/[controller]")] 56 | public class ProductsController 57 | { 58 | [HttpGet] 59 | public string Get() => "Hello World"; 60 | } 61 | ``` 62 | 63 | 8. Run the application and navigate to `/api/products`, it should return the string "Hello World". 64 | 65 | ## Returning JSON from the controller 66 | 67 | 1. Add the `Microsoft.AspNetCore.Mvc.Formatters.Json` to `project.json`: 68 | 69 | ```JSON 70 | "dependencies": { 71 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 72 | "Microsoft.AspNetCore.Mvc.Core": "1.0.0-rc2-final", 73 | "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.0-rc2-final" 74 | }, 75 | ``` 76 | 77 | 2. Configure MVC to use the JSON formatter by changing the `ConfigureServices` in `Startup.cs` to use the following: 78 | 79 | ```C# 80 | public void ConfigureServices(IServiceCollection services) 81 | { 82 | services.AddMvcCore() 83 | .AddJsonFormatters(); 84 | } 85 | ``` 86 | 87 | 3. Add a static list of projects to the `ProductsController`: 88 | 89 | ```C# 90 | public class ProductsController : ControllerBase 91 | { 92 | private static List _products = new List(new[] { 93 | new Product() { Id = 1, Name = "Computer" }, 94 | new Product() { Id = 2, Name = "Radio" }, 95 | new Product() { Id = 3, Name = "Apple" }, 96 | }); 97 | ... 98 | } 99 | 100 | ``` 101 | 4. Change the `Get` method in `ProductsController` to return `IEnumerable` and return the list of products. 102 | 103 | ```C# 104 | public IEnumerable Get() 105 | { 106 | return _products; 107 | } 108 | ``` 109 | 110 | 5. Run the application and navigate to `/api/products`. You should see a JSON payload of with all of the products. 111 | 6. Make a POST request to `/api/products`, you should see a JSON payload with all products. 112 | 7. Restrict the `Get` method to respond to GET requests by adding an `[HttpGet]` attribute to the method: 113 | 114 | ```C# 115 | [HttpGet] 116 | public IEnumerable Get() 117 | { 118 | return _products; 119 | } 120 | ``` 121 | 122 | ## Add a method to Get a single product 123 | 124 | 1. Add a `Get` method to the `ProductsController` that takes an `int id` parameter and returns `Product`. 125 | 126 | ```C# 127 | public Product Get(int id) 128 | { 129 | return _products.SingleOrDefault(p => p.Id == id); 130 | } 131 | ``` 132 | 133 | 2. Add an `HttpGet` route specifying the `id` as a route parameter: 134 | 135 | ```C# 136 | [HttpGet("{id}")] 137 | public Product Get(int id) 138 | { 139 | return _products.SingleOrDefault(p => p.Id == id); 140 | } 141 | ``` 142 | 143 | 3. Run the application, and navigate to `/api/products/1`, you should see a JSON response for the first product. 144 | 4. Navigate to `/api/products/25`, it should return a 204 status code. 145 | 5. Change the `Get` method in the `ProductsController` to return a 404 if the product search returns null. 146 | 147 | ```C# 148 | [HttpGet("{id}")] 149 | public IActionResult Get(int id) 150 | { 151 | var product = _products.SingleOrDefault(p => p.Id == id); 152 | 153 | if (product == null) 154 | { 155 | return NotFound(); 156 | } 157 | 158 | return Ok(product); 159 | } 160 | ``` 161 | 6. Run the application and navigate to `/api/products/40` and it should return a 404 status code. 162 | 163 | ## Adding to the list of products 164 | 165 | 1. Add a `Post` method to `ProductsController` the takes a `Product` as input and adds it to the list of products: 166 | 167 | ```C# 168 | public void Post(Product product) 169 | { 170 | _products.Add(product); 171 | } 172 | ``` 173 | 174 | 1. Add an `[HttpPost]` attribute to the method to constrain it to the POST HTTP verb: 175 | 176 | ```C# 177 | [HttpPost] 178 | public void Post(Product product) 179 | { 180 | _products.Add(product); 181 | } 182 | ``` 183 | 184 | 1. Add a `[FromBody]` to the `product` argument: 185 | 186 | ```C# 187 | [HttpPost] 188 | public void Post([FromBody]Product product) 189 | { 190 | _products.Add(product); 191 | } 192 | ``` 193 | 194 | 1. Run the application and post a JSON payload with the `Content-Type` header `application/json` to `/api/products`: 195 | 196 | ```JSON 197 | { 198 | "Id" : "4", 199 | "Name": "4K Television" 200 | } 201 | ``` 202 | 203 | 1. Make a GET request to `/api/products` and the new entity should show up in the list. 204 | 1. Change the `Post` method to return an `IActionResult` with a 201 status code and the added `Product`: 205 | 206 | ```C# 207 | [HttpPost] 208 | public IActionResult Post([FromBody]Product product) 209 | { 210 | _products.Add(product); 211 | return CreatedAtAction(nameof(Get), new { id = product.Id }, product); 212 | } 213 | ``` 214 | 215 | 1. Add another product to the list by posting to `/api/products`: 216 | 217 | ```JSON 218 | { 219 | "Id": "5", 220 | "Name": "Radio" 221 | } 222 | ``` 223 | 224 | 1. It should return a 201 and the `Product` that was added as JSON. 225 | 226 | ## Add model validation 227 | 228 | 1. Add the `Microsoft.AspNetCore.Mvc.DataAnnotations` package to `project.json`: 229 | 230 | ```JSON 231 | "dependencies": { 232 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 233 | "Microsoft.AspNetCore.Mvc.Core": "1.0.0-rc2-final", 234 | "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.0-rc2-final", 235 | "Microsoft.AspNetCore.Mvc.Formatters.Xml": "1.0.0-rc2-final", 236 | "Microsoft.AspNetCore.Mvc.DataAnnotations": "1.0.0-rc2-final" 237 | }, 238 | ``` 239 | 240 | 1. In `Startup.cs` add a call to `AddDataAnnotations()` chained off the `AddMvcCore` method in `ConfigureServices`: 241 | 242 | ```C# 243 | public void ConfigureServices(IServiceCollection services) 244 | { 245 | services.AddMvcCore() 246 | .AddJsonFormatters() 247 | .AddDataAnnotations(); 248 | } 249 | ``` 250 | 1. Modify the `Product.cs` file and add a `[Required]` attribute to the name property: 251 | 252 | ```C# 253 | public class Product 254 | { 255 | public int Id { get; set; } 256 | 257 | [Required] 258 | public string Name { get; set; } 259 | } 260 | ``` 261 | 262 | 1. In `ProductsController.cs` modify the `Post` method and add a `ModelState.IsValid` check. If the model state is not valid, return a 400 response to the client: 263 | 264 | ```C# 265 | [HttpPost] 266 | public IActionResult Post([FromBody]Product product) 267 | { 268 | if (!ModelState.IsValid) 269 | { 270 | return BadRequest(); 271 | } 272 | 273 | _products.Add(product); 274 | return CreatedAtAction(nameof(Get), new { id = product.Id }, product); 275 | } 276 | ``` 277 | 278 | 1. POST an empty JSON payload to `/api/products` and it should return a 400 response: 279 | 280 | ```JSON 281 | {} 282 | ``` 283 | 284 | 1. Modify the `Post` method to return the validation errors to the client by passing the `ModelState` object to the `BadRequest` method: 285 | 286 | ```C# 287 | [HttpPost] 288 | public IActionResult Post([FromBody]Product product) 289 | { 290 | if (!ModelState.IsValid) 291 | { 292 | return BadRequest(ModelState); 293 | } 294 | 295 | _products.Add(product); 296 | return CreatedAtAction(nameof(Get), new { id = product.Id }, product); 297 | } 298 | ``` 299 | 300 | 1. POST an empty JSON payload to `/api/products` and it should return a 400 response with the validation errors formatted as JSON. 301 | 302 | ## Adding XML support 303 | 304 | 1. Add the `Microsoft.AspNetCore.Mvc.Formatters.Xml` package to `project.json`: 305 | 306 | ```JSON 307 | "dependencies": { 308 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.0-rc2-final", 309 | "Microsoft.AspNetCore.Mvc.Core": "1.0.0-rc2-final", 310 | "Microsoft.AspNetCore.Mvc.Formatters.Json": "1.0.0-rc2-final", 311 | "Microsoft.AspNetCore.Mvc.Formatters.Xml": "1.0.0-rc2-final" 312 | }, 313 | ``` 314 | 315 | 2. In `Startup.cs` add a call to `AddXmlDataContractSerializerFormatters()` chained off the `AddMvcCore` method in `ConfigureServices`: 316 | 317 | ```C# 318 | public void ConfigureServices(IServiceCollection services) 319 | { 320 | services.AddMvcCore() 321 | .AddJsonFormatters() 322 | .AddXmlDataContractSerializerFormatters(); 323 | } 324 | ``` 325 | 3. Run the application and make a request to `/api/products` with the accept header `application/xml`. The response should be an XML payload of the products. 326 | 327 | ## Restrict the ProductsController to be JSON only 328 | 329 | 1. Add a `[Produces("application/json")]` attribute to the `ProductsController` class: 330 | 331 | ```C# 332 | [Produces("application/json")] 333 | [Route("/api/[controller]")] 334 | public class ProductsController : ControllerBase 335 | ``` 336 | 337 | 338 | ## Extra 339 | - Add model validation when the product has a missing Name (and return that back to the client) 340 | - Make the JSON properties camel case 341 | - Write a custom output formatter to prints the product name as plain text 342 | - Replace the static list of products with entity framework in memory store 343 | - Replace the static list with entity framework + sqlite 344 | -------------------------------------------------------------------------------- /Labs/7.5 App building - Attendee List.md: -------------------------------------------------------------------------------- 1 | # App Building: Attendee List 2 | 3 | Using what you've learnt so far, build a simple application for managing a list of course attendees. Use the requirements below as a guide. 4 | 5 | There is a completed application as a further guide in the [App folder](https://github.com/DamianEdwards/aspnetcore-workshop/tree/master/App) of this repository. 6 | 7 | ## Requirements 8 | - You can start with the empty project templaete or the full project template to get going 9 | - HINT: the full project template (with Individual Auth) enables MVC scaffolding which should make it much easier to build parts of the app 10 | - Use Entity Framework Core to manage data, you can choose to use the in-memory provider, SQL, SQL Lite, etc. 11 | - Don't worry too much about making it look pretty with bootstrap, etc. We're just trying to make the application functional 12 | - Attendees should have the following properties 13 | - FirstName (string, required) 14 | - LastName (string, required) 15 | - Email (string, required) 16 | - Company (string) 17 | - There should be pages to: 18 | - List attendees (/) 19 | - View an attendee's details (/{id}) 20 | - Create an attendee (/create) 21 | - Edit an attendee's details (/{id}/edit) 22 | - Delete an attendee (with a confirmation form) (/{id}/delete) 23 | - Pages should include validation for create and update operations 24 | - HINT: Check `ModelState.IsValid` and use the validation attributes on the model class and validation Tag Helpers in the forms 25 | - There should be JSON web APIs to: 26 | - List attendees (GET) 27 | - Retrieve an attendee's details (GET) 28 | - Create an attendee (POST) 29 | - Update an attendee's details (PUT) 30 | - Delete an attendee (DELETE) 31 | - APIs should validate changes for create and update operations and return suitable HTTP responses for operations 32 | - HINT: Use the `CreatedAtAction`, `BadRequest`, and `NoContent` helper methods to return appropriate HTTP status results 33 | - Enable downloading an attendee as a [vCard](https://en.wikipedia.org/wiki/VCard) contact 34 | - HINT: Use a custom `OutputFormatter` and the `Produces` attribute 35 | -------------------------------------------------------------------------------- /Labs/8. Hosting & Deployment.md: -------------------------------------------------------------------------------- 1 | # Hosting & Deployment 2 | 3 | ## Prerequisites (deploying to azure) 4 | - Sign up for an azure account https://azure.microsoft.com/en-us/pricing/free-trial/ 5 | - Download Azure Development tools for Visual Studio https://azure.microsoft.com/en-us/tools/ 6 | - Download and configure git (https://git-scm.com/) if you don't already have it 7 | - Log into Visual Studio (windows only) 8 | - We're going to be deploying the application you built in the previous lab 9 | 10 | ## Deploy via Visual Studio (Windows only) 11 | 12 | 1. Right click on the project and click publish and click on **Microsoft Azure App Service**: 13 | 14 | ![image](https://cloud.githubusercontent.com/assets/95136/15857377/671e1e50-2cbb-11e6-8a8e-ba7873213e67.png) 15 | 16 | 1. Create a new resource group and name it after your project 17 | 18 | ![image](https://cloud.githubusercontent.com/assets/95136/15857406/91a0a116-2cbb-11e6-8fcc-e0bc8dfed211.png) 19 | 20 | 1. Once the resource group is created, follow the instructions and deploy the site to azure. 21 | 22 | ## Deploy via git 23 | 24 | - https://docs.asp.net/en/latest/publishing/azure-continuous-deployment.html 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ASP.NET Core Workshop 2 | 3 | -------------------------------------------------------------------------------- /Slides/ASP.NET What and Why.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shanselman/aspnetcore-workshop/2b4cabb8d71551d0662f3d418c053b92c0785ed0/Slides/ASP.NET What and Why.pptx -------------------------------------------------------------------------------- /notes/davidnotes.md: -------------------------------------------------------------------------------- 1 | # Startup 2 | 3 | - Empty Web Application 4 | - Hosting API `WebHostBuilder` builds the web application 5 | - The `Startup` class is Entry point of the web application 6 | - It's the new `web.config` (even tho there is still a `web.config` specifically for IIS) 7 | - IIS hosting via AspNetCoreModule 8 | - Separation between static content and application code via `webroot` aka `wwwroot` folder 9 | - Configuration via `IConfiguration` 10 | - `ConfigureServices` - for DI 11 | - `Configure` - for the ASP.NET pipeline 12 | - `IApplicationBuilder` stores the list of middleware in the pipeline 13 | - `app.UseXX` register pieces of middleware 14 | - Configure logging providers 15 | - `IHostingEnvironment` - Root of the world for your ASP.NET application 16 | 17 | - .NET Core 18 | .NET Framework 19 | 20 | # Middleware 21 | 22 | - A `module/handler` replacement 23 | - Linear pipeline with ordered components 24 | - Before/After semantics 25 | - Russion doll model 26 | - Dependency injection aware 27 | - Per request scoped services 28 | - Modify the request/response 29 | - Can Add/remove feature interfaces on a per request basis 30 | 31 | 32 | #Configuration 33 | 34 | ## Configuration API 35 | 36 | - Multiple configuration sources 37 | - Command line 38 | - Environment variables 39 | - In memory 40 | - Ini files 41 | - JSON files 42 | - XML 43 | - Custom sources 44 | - Strongly typed using `ConfigurationBinder` 45 | - Configuration change notification 46 | - Accessing configuration in application code 47 | - The project template `appsettings.json` 48 | - Configuring connection strings 49 | - Configuration in Azure Websites 50 | - Storing secrets on developer machines 51 | - User secrets 52 | 53 | ## Options API 54 | - `IOptions` 55 | - Option composition via `IConfigureOptions` 56 | - `IServiceCollection.Configure` 57 | - Accessing `IOptions` in application code 58 | - Options used in middleware 59 | 60 | # Logging & Diagnostics 61 | 62 | 63 | ## Types of errors 64 | - Startup errors 65 | - IIS Module misconfigured 66 | - IIS Module can't start ASP.NET Core app 67 | - ASP.NET Core app starts up and fails 68 | - Per request errors 69 | 70 | ## Logging 71 | - Logging providers 72 | - Console 73 | - Debug 74 | - EventLog 75 | - TraceSource 76 | - 3rd party 77 | - NLog 78 | - Serilog 79 | - Default framework logging 80 | - Hosting 81 | - Entity framework 82 | - MVC 83 | - Filtering logs 84 | 85 | ## Diagnostics 86 | - Exception handler 87 | - Developer Exception Page 88 | - Developer exceptions 89 | - Status code pages 90 | 91 | # Other 92 | - Stdout with the ASP.NET Core module 93 | - Event Log with ASP.NET Core module 94 | - Diagnostics in Azure 95 | 96 | 97 | # MVC API 98 | - Start with ASP.NET Core project and add MVC.Core 99 | - Show basic attribute route 100 | - Add JSON support 101 | - Add Product model 102 | - Add data using the EF in memory store 103 | - Camel case properties 104 | - Write CRUD ProductsController 105 | - GetAll(), Get(id), Post(product), Delete(id) 106 | - Handle unknown products (404) 107 | - Model validation for Post 108 | - Rich model validation with errors flowing to the client 109 | - Add Xml support 110 | - Produces/Consumes 111 | - Custom input and output formatter (custom format) 112 | -------------------------------------------------------------------------------- /outline.md: -------------------------------------------------------------------------------- 1 | # Outline 2 | 3 | ## Day 1 4 | | Time | Title | | 5 | | ---- | ----- | ---- | 6 | | 9:00 AM - 9:15 AM | Introduction & Day Overview | | 7 | | 9:15 AM - 10:00 AM | Session #1: Introduction to the .NET Core SDK | Damian | 8 | | 10:00 AM - 10:15 AM | Break | | 9 | | 10:15 AM - 10:45 AM | Lab #1 | Get bits installed, create first app | 10 | | 10:45 AM - 11:30 AM | Session #2: Introduction to ASP.NET Core | David | 11 | | 11:30 AM - 12:00 PM | Lab #2 | WebHost, Startup, Configuration, Environments, Middleware, & IIS | 12 | | 12:00 PM - 1:00 PM | Lunch | | 13 | | 1:00 PM - 1:45 PM | Session #3: Introduction to Routing & MVC | Damian | 14 | | 1:45 PM - 2:15 PM | Lab #3 | Routing patterns, MVC basics, etc. | 15 | | 2:15 PM - 3:00 PM | Session #4: Logging & Error handling | David | 16 | | 3:00 PM - 3:15 PM | Break | | 17 | | 3:15 PM - 3:45 PM | Lab #4 | Using logging abstractions & providers, diagnostics pages/middleware | 18 | | 3:45 PM - 4:30 PM | Session #5: Dependency Injection & Testing | Damian | 19 | | 4:30 PM - 5:00 PM | Lab #5 | Use dependency injection for application services, add a unit test project | 20 | 21 | ## Day 2 22 | | Time | Title | | 23 | | ---- | ----- | ---- | 24 | | 9:00 AM - 9:15 AM | Introduction & Day Overview | | 25 | | 9:15 AM - 10:00 AM | Session #6: Razor & Tag Helpers | Damian | 26 | | 10:00 AM - 10:15 AM | Break | | 27 | | 10:15 AM - 10:45 AM | Lab #6 | Working with Tag Helpers | 28 | | 10:45 AM - 11:30 AM | Session #7: MVC Web API | David | 29 | | 11:30 AM - 12:00 PM | Lab #7 | | 30 | | 12:00 PM - 1:00 PM | Lunch | | 31 | | 1:00 PM - 3:00 PM | App building: Attendee List | | 32 | | 3:00 PM - 3:15 PM | Break | | 33 | | 3:15 PM - 4:00 PM | Session #8: Deploying to Azure | David | 34 | | 4:00 PM - 4:45 PM | Lab #8 | Deploy app to azure | 35 | | 4:45 PM - 5:00 PM | Summary & Conclusion | | 36 | --------------------------------------------------------------------------------