[
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n# NuGet v3's project.json files produces more ignoreable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016 Christian Horsdal\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Code samples from Microservices in .NET Core 1st edition\nThis repository contains the code from the **first** edition of the book. If you are looking for the code for the **second** edition go to https://github.com/horsdal/microservices-in-dotnet-book-second-edition\n\nThe code samples from my microservices book - https://manning.com/books/microservices-in-net-core\n\n[![](https://images.manning.com/255/340/resize/book/f/562623d-102a-47c4-b12f-4c09af31441e/Horsdal-Microservices-HI.png)](https://www.manning.com/books/microservices-in-net-core)\n\n## About the book\nMicroservices in .NET Core shows you how to build and deploy secure and operations-friendly microservices using Nancy. The book takes you through an introduction to the microservices architectural style. Next, you'll learn important practical aspects of developing microservices from simple core concepts to more sophisticated. Throughout the book, you'll see many code examples implementing it with lightweight .NET technologies—most prominently Nancy. By the end, you'll be able to quickly and easily build reliable and operations-friendly microservices using Nancy, OWIN and other open technologies.\n \n## Branches\nFrom time to time I will update the code use newer versions of libraries as well as .NET Core. I will keep each such update in a branch. The brances in the repository are:\n\n * `master`: The code as it appears in the book\n * `2017-05`: Everything updated to use `csproj` files instead of `project.json` files, so it's compatible with Visual Studio 2017 and newer `dotnet` command line versions. Furhtermore everything is updated to .NET Core 1.1 and Nancy 2.0.0-clinteastwood.\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/.vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \".NET Core Launch (console)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/HelloMicroservices.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false\n        },\n        {\n            \"name\": \".NET Core Launch (web)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/HelloMicroservices.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false,\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            }\n        },\n        {\n            \"name\": \".NET Core Attach\",\n            \"type\": \"coreclr\",\n            \"request\": \"attach\",\n            \"processName\": \"<example>\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/.vscode/tasks.json",
    "content": "{\n    \"version\": \"0.1.0\",\n    \"command\": \"dotnet\",\n    \"isShellCommand\": true,\n    \"args\": [],\n    \"tasks\": [\n        {\n            \"taskName\": \"build\",\n            \"args\": [],\n            \"isBuildCommand\": true,\n            \"problemMatcher\": \"$msCompile\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/CurrentDateTimeModule.cs",
    "content": "namespace HelloMicroservices\n{\n  using System;\n  using Nancy;\n\n  public class CurrentDateTimeModule\n    : NancyModule\n  {\n    public CurrentDateTimeModule()\n    {\n      Get(\"/\", _ => DateTime.UtcNow);\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/HelloMicroservices.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>74316f9a-d6b2-451a-b709-b3dc753d9a8c</ProjectGuid>\n    <RootNamespace>HelloMicroservices</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace HelloMicroservices\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"HelloMicroservices\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/Startup.cs",
    "content": "namespace HelloMicroservices\n{\n  using Microsoft.AspNetCore.Builder;\n  using Nancy.Owin;\n\n  public class Startup\n  {\n    public void Configure(IApplicationBuilder app)\n    {\n      app.UseOwin().UseNancy();\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\"\n  },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"HelloMicroservices\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter01/HelloMicroservices/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter01/ch01.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25420.1\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"HelloMicroservices\", \"HelloMicroservices\\HelloMicroservices.xproj\", \"{74316F9A-D6B2-451A-B709-B3DC753D9A8C}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{74316F9A-D6B2-451A-B709-B3DC753D9A8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{74316F9A-D6B2-451A-B709-B3DC753D9A8C}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{74316F9A-D6B2-451A-B709-B3DC753D9A8C}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{74316F9A-D6B2-451A-B709-B3DC753D9A8C}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/.vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \".NET Core Launch (console)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/ShoppingCart.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false\n        },\n        {\n            \"name\": \".NET Core Launch (web)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/ShoppingCart.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false,\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            }\n        },\n        {\n            \"name\": \".NET Core Attach\",\n            \"type\": \"coreclr\",\n            \"request\": \"attach\",\n            \"processName\": \"<example>\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter02/ShoppingCart/.vscode/tasks.json",
    "content": "{\n    \"version\": \"0.1.0\",\n    \"command\": \"dotnet\",\n    \"isShellCommand\": true,\n    \"args\": [],\n    \"tasks\": [\n        {\n            \"taskName\": \"build\",\n            \"args\": [],\n            \"isBuildCommand\": true,\n            \"problemMatcher\": \"$msCompile\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter02/ShoppingCart/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/EventFeed/Event.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using System;\n\n  public struct Event\n  {\n    public long SequenceNumber { get; }\n    public DateTimeOffset OccuredAt { get; }\n    public string Name { get; }\n    public object Content { get; }\n\n    public Event(\n      long sequenceNumber,\n      DateTimeOffset occuredAt,\n      string name,\n      object content)\n    {\n      this.SequenceNumber = sequenceNumber;\n      this.OccuredAt = occuredAt;\n      this.Name = name;\n      this.Content = content;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/EventFeed/EventStore.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Threading;\n  using ShoppingCart;\n\n  public class EventStore : IEventStore\n  {\n    private static long currentSequenceNumber = 0;\n    private static readonly IList<Event> database = new List<Event>();\n\n    public IEnumerable<Event> GetEvents(\n      long firstEventSequenceNumber,\n      long lastEventSequenceNumber) \n      => database\n          .Where(e =>\n            e.SequenceNumber >= firstEventSequenceNumber &&\n            e.SequenceNumber <= lastEventSequenceNumber)\n          .OrderBy(e => e.SequenceNumber);\n\n    public void Raise(string eventName, object content)\n    {\n      var seqNumber = Interlocked.Increment(ref currentSequenceNumber);\n      database.Add(\n        new Event(\n          seqNumber,\n          DateTimeOffset.UtcNow,\n          eventName,\n          content));\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/EventFeed/EventsFeedModule.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using Nancy;\n\n  public class EventsFeedModule : NancyModule\n  {\n    public EventsFeedModule(IEventStore eventStore) : base(\"/events\")\n    {\n      Get(\"/\", _ =>\n      {\n        long firstEventSequenceNumber, lastEventSequenceNumber;\n        if (!long.TryParse(this.Request.Query.start.Value, \n          out firstEventSequenceNumber))\n          firstEventSequenceNumber = 0;\n        if (!long.TryParse(this.Request.Query.end.Value, \n          out lastEventSequenceNumber))\n          lastEventSequenceNumber = long.MaxValue;\n\n        return \n          eventStore.GetEvents(\n            firstEventSequenceNumber,\n            lastEventSequenceNumber);\n      });\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter02/ShoppingCart/EventFeed/IEventStore.cs",
    "content": "﻿using System.Collections.Generic;\nusing ShoppingCart.ShoppingCart;\n\nnamespace ShoppingCart.EventFeed\n{\n  public interface IEventStore\n  {\n    IEnumerable<Event> GetEvents(long firstEventSequenceNumber, long lastEventSequenceNumber);\n    void Raise(string eventName, object content);\n  }\n}"
  },
  {
    "path": "src/Chapter02/ShoppingCart/IProductCatalogueClient.cs",
    "content": "﻿namespace ShoppingCart\n{\n  using System.Collections.Generic;\n  using System.Threading.Tasks;\n  using ShoppingCart;\n\n  public interface IProductCatalogueClient\n  {\n    Task<IEnumerable<ShoppingCartItem>>\n      GetShoppingCartItems(int[] productCatalogueIds);\n  }\n}"
  },
  {
    "path": "src/Chapter02/ShoppingCart/ProductCatalogueClient.cs",
    "content": "﻿namespace ShoppingCart\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Threading.Tasks;\n  using System.Net.Http;\n  using System.Threading;\n  using Newtonsoft.Json;\n  using Polly;\n  using ShoppingCart;\n\n  public class ProductCatalogueClient : IProductCatalogueClient\n  {\n    private static Policy exponentialRetryPolicy =\n      Policy\n        .Handle<Exception>()\n        .WaitAndRetryAsync(\n          3, \n          attempt => TimeSpan.FromMilliseconds(100 * Math.Pow(2, attempt)), (ex, _) => Console.WriteLine(ex.ToString()));\n\n    private static string productCatalogueBaseUrl =\n      @\"http://private-05cc8-chapter2productcataloguemicroservice.apiary-mock.com\";\n    private static string getProductPathTemplate =\n      \"/products?productIds=[{0}]\";\n\n    public Task<IEnumerable<ShoppingCartItem>>\n      GetShoppingCartItems(int[] productCatalogueIds) =>\n      exponentialRetryPolicy\n        .ExecuteAsync(async () => await GetItemsFromCatalogueService(productCatalogueIds).ConfigureAwait(false));\n\n    private async Task<IEnumerable<ShoppingCartItem>>\n      GetItemsFromCatalogueService(int[] productCatalogueIds)\n    {\n      var response = await\n        RequestProductFromProductCatalogue(productCatalogueIds).ConfigureAwait(false);\n      return await ConvertToShoppingCartItems(response).ConfigureAwait(false);\n    }\n\n    private static async Task<HttpResponseMessage> RequestProductFromProductCatalogue(int[] productCatalogueIds)\n    {\n      var productsResource = string.Format(\n        getProductPathTemplate, string.Join(\",\", productCatalogueIds));\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri(productCatalogueBaseUrl);\n        return await httpClient.GetAsync(productsResource).ConfigureAwait(false);\n      }\n    }\n\n    private static async Task<IEnumerable<ShoppingCartItem>> ConvertToShoppingCartItems(HttpResponseMessage response)\n    {\n      response.EnsureSuccessStatusCode();\n      var products = \n        JsonConvert.DeserializeObject<List<ProductCatalogueProduct>>(await response.Content.ReadAsStringAsync().ConfigureAwait(false));\n      return\n        products\n          .Select(p => new ShoppingCartItem(\n            int.Parse(p.ProductId),\n            p.ProductName,\n            p.ProductDescription,\n            p.Price\n        ));\n    }\n\n    private class ProductCatalogueProduct\n    {\n      public string ProductId { get; set; }\n      public string ProductName { get; set; }\n      public string ProductDescription { get; set; }\n      public Money Price { get; set; }\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter02/ShoppingCart/Program.cs",
    "content": "using System.IO;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace ShoppingCart\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"ShoppingCart\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/ShoppingCart/IShoppingCartStore.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  public interface IShoppingCartStore\n  {\n    ShoppingCart Get(int userId);\n    void Save(ShoppingCart shoppingCart);\n  }\n}"
  },
  {
    "path": "src/Chapter02/ShoppingCart/ShoppingCart/ShoppingCart.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using EventFeed;\n\n  public class ShoppingCart\n  {\n    private HashSet<ShoppingCartItem> items = new HashSet<ShoppingCartItem>();\n\n    public int UserId { get; }\n    public IEnumerable<ShoppingCartItem> Items { get { return items; } }\n\n    public ShoppingCart(int userId)\n    {\n      this.UserId = userId;\n    }\n\n    public void AddItems(\n      IEnumerable<ShoppingCartItem> shoppingCartItems,\n      IEventStore eventStore)\n    {\n      foreach (var item in shoppingCartItems)\n        if (this.items.Add(item))\n          eventStore.Raise(\n            \"ShoppingCartItemAdded\",\n            new { UserId, item });\n    }\n\n    public void RemoveItems(\n      int[] productCatalogueIds,\n      IEventStore eventStore)\n    {\n      items.RemoveWhere(i => productCatalogueIds.Contains(i.ProductCatalogueId));\n    }\n  }\n\n  public class ShoppingCartItem\n  {\n    public int ProductCatalogueId { get; }\n    public string ProductName { get; }\n    public string Desscription { get; }\n    public Money Price { get; }\n\n    public ShoppingCartItem(\n      int productCatalogueId,\n      string productName,\n      string description,\n      Money price)\n    {\n      this.ProductCatalogueId = productCatalogueId;\n      this.ProductName = productName;\n      this.Desscription = description;\n      this.Price = price;\n    }\n\n    public override bool Equals(object obj)\n    {\n      if (obj == null || GetType() != obj.GetType())\n      {\n        return false;\n      }\n\n      var that = obj as ShoppingCartItem;\n      return this.ProductCatalogueId.Equals(that.ProductCatalogueId);\n    }\n\n    // override object.GetHashCode\n    public override int GetHashCode()\n    {\n      return this.ProductCatalogueId.GetHashCode();\n    }\n  }\n\n  public class Money\n  {\n    public string Currency { get; }\n    public decimal Amount { get; }\n\n    public Money(string currency, decimal amount)\n    {\n      this.Currency = currency;\n      this.Amount = amount;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/ShoppingCart/ShoppingCartModule.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using EventFeed;\n  using Nancy;\n  using Nancy.ModelBinding;\n\n  public class ShoppingCartModule : NancyModule\n  {\n    public ShoppingCartModule(\n      IShoppingCartStore shoppingCartStore,\n      IProductCatalogueClient productCatalogue,\n      IEventStore eventStore) \n      : base(\"/shoppingcart\")\n    {\n      Get(\"/{userid:int}\", parameters =>\n      {\n        var userId = (int) parameters.userid;\n        return shoppingCartStore.Get(userId);\n      });\n\n      Post(\"/{userid:int}/items\", async (parameters, _) =>\n      {\n        var productCatalogueIds = this.Bind<int[]>();\n        var userId = (int) parameters.userid;\n\n        var shoppingCart = shoppingCartStore.Get(userId);\n        var shoppingCartItems = await productCatalogue.GetShoppingCartItems(productCatalogueIds).ConfigureAwait(false);\n        shoppingCart.AddItems(shoppingCartItems, eventStore);\n        shoppingCartStore.Save(shoppingCart);\n\n        return shoppingCart;\n      });\n\n      Delete(\"/{userid:int}/items\", parameters =>\n      {\n        var productCatalogueIds = this.Bind<int[]>();\n        var userId = (int)parameters.userid;\n\n        var shoppingCart = shoppingCartStore.Get(userId);\n        shoppingCart.RemoveItems(productCatalogueIds, eventStore);\n        shoppingCartStore.Save(shoppingCart);\n\n        return shoppingCart;\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/ShoppingCart/ShoppingCartStore.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using System.Collections.Generic;\n\n  public class ShoppingCartStore : IShoppingCartStore\n  {\n    private static readonly Dictionary<int, ShoppingCart> database = new Dictionary<int, ShoppingCart>();\n\n    public ShoppingCart Get(int userId)\n    {\n      if (!database.ContainsKey(userId))\n        database[userId] = new ShoppingCart(userId);\n      return database[userId];\n    }\n\n    public void Save(ShoppingCart shoppingCart)\n    {\n      // Nothing needed. Saving would be needed with a real DB\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter02/ShoppingCart/ShoppingCart.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>10e4f601-c16b-4936-a7b4-d32d799318d1</ProjectGuid>\n    <RootNamespace>ShoppingCart</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter02/ShoppingCart/Startup.cs",
    "content": "namespace ShoppingCart\n{\n    using Microsoft.AspNetCore.Builder;\n    using Nancy;\n    using Nancy.Configuration;\n    using Nancy.Owin;\n\n    public class Startup\n    {\n        public void Configure(IApplicationBuilder app)\n        {\n            app.UseOwin().UseNancy(opt => opt.Bootstrapper = new TracingBootstrapper());\n        }\n    }    \n    \n    public class TracingBootstrapper : Nancy.DefaultNancyBootstrapper\n    {\n        public override void Configure(INancyEnvironment env)\n        {\n            env.Tracing(enabled: true, displayErrorTraces: true);            \n        }\n    } \n}\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"System.Net.Http\": \"4.0.1\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"Polly\": \"4.2.1\"\n  },\n\n  \"tools\": {\n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"dnxcore50\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"HelloMicroservices\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter02/ShoppingCart/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter02/ch02.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25420.1\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"ShoppingCart\", \"ShoppingCart\\ShoppingCart.xproj\", \"{10E4F601-C16B-4936-A7B4-D32D799318D1}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{10E4F601-C16B-4936-A7B4-D32D799318D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{10E4F601-C16B-4936-A7B4-D32D799318D1}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{10E4F601-C16B-4936-A7B4-D32D799318D1}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{10E4F601-C16B-4936-A7B4-D32D799318D1}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Chapter04/.idea.Ch4/riderModule.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"RIDER_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\">\n    <content url=\"file://$MODULE_DIR$/..\">\n      <sourceFolder url=\"file://$MODULE_DIR$/..\" isTestSource=\"false\" />\n    </content>\n    <content url=\"file://C:/projects/Nancy/src/Nancy\">\n      <sourceFolder url=\"file://C:/projects/Nancy/src/Nancy\" isTestSource=\"false\" />\n    </content>\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n  </component>\n</module>"
  },
  {
    "path": "src/Chapter04/ApiGatewayMock/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter04/ApiGatewayMock/ApiGatewayMock.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>fe109a02-bf1b-46fc-87c8-2a68781ce8a4</ProjectGuid>\n    <RootNamespace>ApiGatewayMock</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter04/ApiGatewayMock/LoyalProgramClient.cs",
    "content": "using System;\nusing System.Net.Http;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json;\nusing Polly;\n\nnamespace ApiGatewayMock\n{\n    public class LoyaltyProgramClient\n    {\n        private static Policy exponentialRetryPolicy =\n          Policy\n            .Handle<Exception>()\n            .WaitAndRetryAsync(\n              3,\n              attempt => TimeSpan.FromMilliseconds(100 * Math.Pow(2, attempt)),\n              (_, __) => Console.WriteLine(\"retrying...\" + _)\n            );\n\n        private string hostName;\n\n        public LoyaltyProgramClient(string loyalProgramMicroserviceHostName)\n        {\n            this.hostName = loyalProgramMicroserviceHostName;\n        }\n\n        public async Task<HttpResponseMessage> QueryUser(int userId)\n         {\n            return await exponentialRetryPolicy.ExecuteAsync(() => DoUserQuery(userId));\n         }\n\n        private async Task<HttpResponseMessage> DoUserQuery(int userId)\n        {\n            var userResource = $\"/users/{userId}\";\n            using(var httpClient = new HttpClient())\n            { \n              httpClient.BaseAddress = new Uri($\"http://{this.hostName}\");\n              var response = await httpClient.GetAsync(userResource);\n              ThrowOnTransientFailure(response);\n              return response;\n            }\n        }\n\n        private static void ThrowOnTransientFailure(HttpResponseMessage response)\n        {\n            if (((int)response.StatusCode) < 200 || ((int)response.StatusCode) > 499) throw new Exception(response.StatusCode.ToString());\n        }\n\n        public async Task<HttpResponseMessage> RegisterUser(LoyaltyProgramUser newUser)\n        {\n            return await exponentialRetryPolicy.ExecuteAsync(() => DoRegisterUser(newUser));\n        }\n\n        private async Task<HttpResponseMessage> DoRegisterUser(LoyaltyProgramUser newUser)\n        {\n            using(var httpClient = new HttpClient())\n            { \n              httpClient.BaseAddress = new Uri($\"http://{this.hostName}\");\n              var response = await httpClient.PostAsync(\"/users/\", new  StringContent(JsonConvert.SerializeObject(newUser), Encoding.UTF8, \"application/json\"));\n              ThrowOnTransientFailure(response);\n              return response;\n            }\n        }\n\n        public async Task<HttpResponseMessage> UpdateUser(LoyaltyProgramUser user)\n        {\n            return await exponentialRetryPolicy.ExecuteAsync(() => DoUpdateUser(user));\n        }\n\n        private async Task<HttpResponseMessage> DoUpdateUser(LoyaltyProgramUser user)\n        {\n            using(var httpClient = new HttpClient())\n            { \n              httpClient.BaseAddress = new Uri($\"http://{this.hostName}\");\n              var response = await httpClient.PutAsync($\"/users/{user.Id}\", new  StringContent(JsonConvert.SerializeObject(user), Encoding.UTF8, \"application/json\"));\n              ThrowOnTransientFailure(response);\n              return response;\n            }\n        }\n    }\n\n  public class LoyaltyProgramUser\n  {\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public int LoyaltyPoints { get; set; }\n    public LoyaltyProgramSettings Settings { get; set; }\n  }\n\n  public class LoyaltyProgramSettings\n  {\n    public string[] Interests { get; set; }\n  }\n\n}\n"
  },
  {
    "path": "src/Chapter04/ApiGatewayMock/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json;\nusing static System.Console;\n\nnamespace ApiGatewayMock\n{\n    public class Program\n    {\n        private LoyaltyProgramClient client;\n\n        public static void Main(string[] arg) => new Program().Main();\n\n        public  void Main()\n        {\n            this.client = new LoyaltyProgramClient(\"localhost:5000\");\n            WriteLine(\"Welcome to the API Gateway Mock.\");\n\n            var cont = true;\n            while (cont)\n            {\n                WriteLine();\n                WriteLine();\n                WriteLine(\"********************\");\n                WriteLine(\"Choose one of:\");\n                WriteLine(\"q <userid> - to query the Loyalty Program Microservice for a user with id <userid>.\");\n                WriteLine(\"r <userid> - to register a user with id <userid> with the Loyalty Program Microservice.\");\n                WriteLine(\"u <userid> <interests> - to update a user with new comman separated interests\");\n                WriteLine(\"exit - to exit\");\n                WriteLine(\"********************\");\n                var cmd = ReadLine();\n                cont = ProcessCommand(cmd);\n            }\n        }\n\n        private bool ProcessCommand(string cmd)\n        {\n            if (\"exit\".Equals(cmd))\n                return false;\n            if (cmd.StartsWith(\"q\"))\n                ProcessUserQuery(cmd);\n            else if (cmd.StartsWith(\"r\"))\n                ProcessUserRegistration(cmd);\n            else if (cmd.StartsWith(\"u\"))\n                ProcessUpdateUser(cmd);\n            else\n              WriteLine(\"Did not understand command :(\");\n            return true;\n        }\n\n        private void ProcessUserQuery(string cmd)\n        {\n            int userId;\n            if (!int.TryParse(cmd.Substring(1), out userId))\n                WriteLine(\"Please specify user id as an int\");\n            else\n            {\n                var response = this.client.QueryUser(userId).Result;\n                PrettyPrintResponse(response);\n            }\n        }\n\n        private void ProcessUserRegistration(string cmd)\n        {\n            var newUser = new LoyaltyProgramUser { Name = cmd.Substring(1).Trim() };\n            var response = this.client.RegisterUser(newUser).Result;\n            PrettyPrintResponse(response);\n        }\n\n        private static async void PrettyPrintResponse(HttpResponseMessage response)\n        {\n            WriteLine(\"Status code: \" + response?.StatusCode.ToString() ?? \"command failed\");\n            WriteLine(\"Headers: \" + response?.Headers.Aggregate(\"\", (acc, h) => acc + \"\\n\\t\" + h.Key + \": \" + h.Value) ?? \"\");\n            WriteLine(\"Body: \" + await response?.Content.ReadAsStringAsync() ?? \"\");\n        }\n        \n        private async void ProcessUpdateUser(string cmd)\n        {\n            int userId;\n            if (!int.TryParse(cmd.Split(' ').Skip(1).First(), out userId))\n              WriteLine(\"Plaese speciffy user id as an int\");\n            else\n            {\n              var response = this.client.QueryUser(userId).Result;\n              if (response.StatusCode == System.Net.HttpStatusCode.OK)\n              {\n                var user = JsonConvert.DeserializeObject<LoyaltyProgramUser>(await response.Content.ReadAsStringAsync());\n                var newInterests = cmd.Substring(cmd.IndexOf(' ', 2)).Split(',').Select(i => i.Trim());\n                user.Settings = \n                  new LoyaltyProgramSettings \n                  { \n                    Interests =\n                      user.Settings?.Interests.Union(newInterests).ToArray() \n                      ??  newInterests.ToArray()\n                   };\n                 PrettyPrintResponse(this.client.UpdateUser(user).Result);\n              }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter04/ApiGatewayMock/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n  \"buildOptions\": {\n    \"emitEntryPoint\": true\n  },\n\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"type\": \"platform\",\n      \"version\": \"1.0.0\"\n    },\n    \"Newtonsoft.Json\": \"8.0.3\",\n    \"Polly\": \"4.2.1\",\n    \"System.Net.Http\": \"4.0.1\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": \"dnxcore50\"\n    }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"ApiGatewayMock\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter04/Ch4.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25123.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgram\", \"LoyaltyProgram\\LoyaltyProgram.xproj\", \"{4BED3C45-E8C3-4345-A08F-249A39A256EB}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"ApiGatewayMock\", \"ApiGatewayMock\\ApiGatewayMock.xproj\", \"{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgramEventConsumer\", \"LoyaltyProgramEventConsumer\\LoyaltyProgramEventConsumer.xproj\", \"{47349717-585A-43EE-96E8-7D5249CB431D}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/Bootstrapper.cs",
    "content": "namespace LoyaltyProgram\n{\n  using System;\n  using Nancy;\n  using Nancy.Bootstrapper;\n\n  public class Bootstrapper : DefaultNancyBootstrapper\n  {\n    protected override Func<ITypeCatalog, NancyInternalConfiguration> InternalConfiguration\n     => NancyInternalConfiguration.WithOverrides(builder => builder.StatusCodeHandlers.Clear()); \n  }\n}\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/LoyaltyProgram.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>4bed3c45-e8c3-4345-a08f-249a39a256eb</ProjectGuid>\n    <RootNamespace>LoyaltyProgram</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace LoyaltyProgram\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"LoyaltyProgram\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/Startup.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace LoyaltyProgram\n{\n    public class Startup\n    {\n        // This method gets called by the runtime. Use this method to add services to the container.\n        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940\n        public void ConfigureServices(IServiceCollection services)\n        {\n        }\n\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n        public void Configure(IApplicationBuilder app)\n        {\n            app.Run(async (context) =>\n            {\n                await context.Response.WriteAsync(\"Hello World!\");\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/UsersModule.cs",
    "content": "namespace LoyaltyProgram\n{\n  using System.Collections.Generic;\n  using Nancy;\n  using Nancy.ModelBinding;\n\n  public class UsersModule : NancyModule\n  {\n    private static IDictionary<int, LoyaltyProgramUser> registeredUsers =\n      new Dictionary<int, LoyaltyProgramUser>();\n\n    public UsersModule() : base(\"/users\")\n    {\n      Get(\"/\", _ => registeredUsers.Values);\n\n      Get(\"/{userId:int}\", parameters =>\n      {\n        int userId = parameters.userId;\n        if (registeredUsers.ContainsKey(userId))\n          return registeredUsers[userId];\n        else\n          return HttpStatusCode.NotFound;\n      });\n\n      Post(\"/\", _ =>\n      {\n        var newUser = this.Bind<LoyaltyProgramUser>();\n        this.AddRegisteredUser(newUser);\n        return this.CreatedResponse(newUser);\n      });\n\n      Put(\"/{userId:int}\", parameters =>\n      {\n        int userId = parameters.userId;\n        var updatedUser = this.Bind<LoyaltyProgramUser>();\n        registeredUsers[userId] = updatedUser;\n        return updatedUser;\n      });\n    }\n\n    private dynamic CreatedResponse(LoyaltyProgramUser newUser)\n    {\n      return\n          this.Negotiate\n              .WithStatusCode(HttpStatusCode.Created)\n              .WithHeader(\"Location\", this.Request.Url.SiteBase + \"/users/\" + newUser.Id)\n              .WithModel(newUser);\n    }\n\n    private void AddRegisteredUser(LoyaltyProgramUser newUser)\n    {\n      var userId = registeredUsers.Count;\n      newUser.Id = userId;\n      registeredUsers[userId] = newUser;\n    }\n  }\n\n  public class LoyaltyProgramUser\n  {\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public int LoyaltyPoints { get; set; }\n    public LoyaltyProgramSettings Settings { get; set; }\n  }\n\n  public class LoyaltyProgramSettings\n  {\n    public string[] Interests { get; set; }\n  }\n}\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/YamlSerializerDeserializer.cs",
    "content": "namespace LoyaltyProgram\n{\n   using System;\n   using System.Collections.Generic;\n   using System.IO;\n   using Nancy;\n   using Nancy.ModelBinding;\n   using Nancy.Responses.Negotiation;\n   using YamlDotNet.Serialization;\n\n    public class YamlBodyDeserializer : IBodyDeserializer\n    {\n        public bool CanDeserialize(MediaRange mediaRange, BindingContext context)\n          => mediaRange.Subtype.ToString().EndsWith(\"yaml\");\n\n        public object Deserialize(MediaRange mediaRange, Stream bodyStream, BindingContext context)\n        {\n          var yamlDeserializer = new Deserializer();\n          var reader = new StreamReader(bodyStream);\n          return yamlDeserializer.Deserialize(reader, context.DestinationType);\n        }\n    }\n\n    public class YamlBodySerializer : IResponseProcessor\n    {\n        public IEnumerable<Tuple<string, MediaRange>> ExtensionMappings\n        {\n            get\n            {\n              yield return new Tuple<string, MediaRange>(\"yaml\", new MediaRange(\"application/yaml\"));\n            }\n        }\n\n        public ProcessorMatch CanProcess(MediaRange requestedMediaRange, dynamic model, NancyContext context)\n          =>\n            requestedMediaRange.Subtype.ToString().EndsWith(\"yaml\") \n            ? new ProcessorMatch { ModelResult = MatchResult.DontCare, RequestedContentTypeResult = MatchResult.NonExactMatch}\n            : ProcessorMatch.None;         \n\n        public Response Process(MediaRange requestedMediaRange, dynamic model, NancyContext context)\n          =>\n            new Response\n            {\n              Contents = stream =>\n              {\n                  var yamlSerializer = new Serializer();\n                  var streamWriter = new StreamWriter(stream);\n                  yamlSerializer.Serialize(streamWriter, model);\n                  streamWriter.Flush();\n              },\n              ContentType = \"application/yaml\"\n            };      \n    }\n}"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"YamlDotNet\": \"3.8.0-pre233\"\n  },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgram\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgram/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgramEventConsumer/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter04/LoyaltyProgramEventConsumer/LoyaltyProgramEventConsumer.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>47349717-585a-43ee-96e8-7d5249cb431d</ProjectGuid>\n    <RootNamespace>LoyaltyProgramEventConsumer</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter04/LoyaltyProgramEventConsumer/Program.cs",
    "content": "namespace LoyaltyProgramEventConsumer\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Net;\n  using System.Net.Http;\n  using System.ServiceProcess;\n  using System.Threading.Tasks;\n  using System.Timers;\n  using Newtonsoft.Json;\n\n  using static System.Console;\n\n  public class EventSubscriber\n  {\n    private readonly string loyaltyProgramHost;\n    private long start = 0, chunkSize = 100;\n    private readonly Timer timer;\n\n    public EventSubscriber(string loyaltyProgramHost)\n    {\n      WriteLine(\"created\");\n      this.loyaltyProgramHost = loyaltyProgramHost;\n      this.timer = new Timer(10 * 1000);\n      this.timer.AutoReset = false;\n      this.timer.Elapsed += (_, __) => SubscriptionCycleCallback().Wait();\n    }\n\n    private async Task SubscriptionCycleCallback()\n    {\n      var response = await ReadEvents();\n      if (response.StatusCode == HttpStatusCode.OK)\n        HandleEvents(await response.Content.ReadAsStringAsync());\n      this.timer.Start();\n    }\n\n    private async Task<HttpResponseMessage> ReadEvents()\n    {\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri($\"http://{this.loyaltyProgramHost}\");\n        var response = await httpClient.GetAsync($\"/events/?start={this.start}&end={this.start + this.chunkSize}\");\n        PrettyPrintResponse(response);\n        return response;\n      }\n    }\n\n    private void HandleEvents(string content)\n    {\n      WriteLine(\"Handling events\");\n      var events = JsonConvert.DeserializeObject<IEnumerable<Event>>(content);\n      WriteLine(events);\n      WriteLine(events.Count());\n      foreach (var ev in events)\n      {\n        WriteLine(ev.Content);\n        dynamic eventData = ev.Content;\n        WriteLine(\"product name from data: \" + (string)eventData.item.productName);\n        this.start = Math.Max(this.start, ev.SequenceNumber + 1);\n      }\n    }\n\n\n    public void Start()\n    {\n      this.timer.Start();\n    }\n\n    public void Stop()\n    {\n      this.timer.Stop();\n    }\n\n    private static async void PrettyPrintResponse(HttpResponseMessage response)\n    {\n      WriteLine(\"Status code: \" + response?.StatusCode.ToString() ?? \"command failed\");\n      WriteLine(\"Headers: \" + response?.Headers.Aggregate(\"\", (acc, h) => acc + \"\\n\\t\" + h.Key + \": \" + h.Value) ?? \"\");\n      WriteLine(\"Body: \" + await response?.Content.ReadAsStringAsync() ?? \"\");\n    }\n  }\n\n  public struct Event\n  {\n    public long SequenceNumber { get; set; }\n    public string Name { get; set; }\n    public object Content { get; set; }\n  }\n\n  public class Program : ServiceBase\n  {\n    private EventSubscriber subscriber;\n\n    public static void Main(string[] args) => new Program().Main();\n\n    public void Main()\n    {\n      this.subscriber = new EventSubscriber(\"localhost:5000\");\n      //Run(this);\n      OnStart(null);\n      ReadLine();\n    }\n\n    protected override void OnStart(string[] args)\n    {\n      this.subscriber.Start();\n    }\n\n    protected override void OnStop()\n    {\n      this.subscriber.Stop();\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter04/LoyaltyProgramEventConsumer/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n  \"buildOptions\": {\n    \"emitEntryPoint\": true\n  },\n\n  \"dependencies\": {\n    \"Newtonsoft.Json\": \"8.0.3\",\n    \"System.ServiceProcess.ServiceController\": \"4.1.0\",\n    \"System.Net.Http\": \"4.1.0\"\n  },\n\n  \"frameworks\": {\n    \"net461\": { }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgramEventConsumer\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/Ch5.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25123.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"ShoppingCart\", \"ShoppingCart\\ShoppingCart.xproj\", \"{10E4F601-C16B-4936-A7B4-D32D799318D1}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"ProductCatalog\", \"ProductCatalog\\ProductCatalog.xproj\", \"{46381F82-A705-496C-A0DF-7406EB036A22}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{10E4F601-C16B-4936-A7B4-D32D799318D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{10E4F601-C16B-4936-A7B4-D32D799318D1}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{10E4F601-C16B-4936-A7B4-D32D799318D1}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{10E4F601-C16B-4936-A7B4-D32D799318D1}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{46381F82-A705-496C-A0DF-7406EB036A22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{46381F82-A705-496C-A0DF-7406EB036A22}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{46381F82-A705-496C-A0DF-7406EB036A22}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{46381F82-A705-496C-A0DF-7406EB036A22}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Chapter05/ProductCatalog/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter05/ProductCatalog/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter05/ProductCatalog/ProductCatalog.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>46381f82-a705-496c-a0df-7406eb036a22</ProjectGuid>\n    <RootNamespace>ProductCatalog</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter05/ProductCatalog/ProductsModule.cs",
    "content": "namespace ProductCatalog\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using Nancy;\n  \n  public class ProductsModule : NancyModule\n  {\n    public ProductsModule(ProductStore productStore) : base(\"/products\")\n    {\n      Get(\"\", _ =>\n      {\n        string productIdsString = this.Request.Query.productIds;\n        var productIds = ParseProductIdsFromQueryString(productIdsString);\n        var products = productStore.GetProductsByIds(productIds);\n\n        return\n          this\n           .Negotiate\n           .WithModel(products)\n           .WithHeader(\"cache-control\", \"max-age:86400\");\n      });\n    }\n\n    private static IEnumerable<int> ParseProductIdsFromQueryString(string productIdsString)\n    {\n        return productIdsString.Split(',').Select(s => s.Replace(\"[\", \"\").Replace(\"]\", \"\")).Select(int.Parse);\n    }\n  }\n\n  public interface ProductStore\n  {\n      IEnumerable<ProductCatalogProduct> GetProductsByIds(IEnumerable<int> productIds);\n  }\n\n  public class StaticProductStore : ProductStore\n  {\n    public IEnumerable<ProductCatalogProduct> GetProductsByIds(IEnumerable<int> productIds)\n    {\n      return productIds.Select(id => new ProductCatalogProduct(id, \"foo\" + id, \"bar\", new Money()));\n    }\n  }\n\n  public class ProductCatalogProduct                                \n  {\n    public ProductCatalogProduct(int productId, string productName, string description, Money price)\n    {\n        this.ProductId = productId.ToString();\n        this.ProductName = productName;\n        this.ProductDescription = description;\n        this.Price = price;\n    }\n    public string ProductId { get; private set; }\n    public string ProductName { get; private set; }\n    public string ProductDescription { get; private set; }\n    public Money Price { get; private set; }\n  }\n    \n  public class Money { }\n}"
  },
  {
    "path": "src/Chapter05/ProductCatalog/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace ProductCatalog\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter05/ProductCatalog/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"ProductCatalog\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ProductCatalog/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter05/ProductCatalog/Startup.cs",
    "content": "namespace ProductCatalog\n{\n  using Microsoft.AspNetCore.Builder;\n  using Nancy.Owin;\n\n  public class Startup\n  {\n    public void Configure(IApplicationBuilder app)\n    {\n      app.UseOwin().UseNancy();\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ProductCatalog/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspnetCore.Owin\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\"\n  },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"ProductCatalog\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ProductCatalog/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/.vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \".NET Core Launch (console)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/ShoppingCart.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false\n        },\n        {\n            \"name\": \".NET Core Launch (web)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/ShoppingCart.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false,\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            }\n        },\n        {\n            \"name\": \".NET Core Attach\",\n            \"type\": \"coreclr\",\n            \"request\": \"attach\",\n            \"processName\": \"<example>\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/.vscode/tasks.json",
    "content": "{\n    \"version\": \"0.1.0\",\n    \"command\": \"dotnet\",\n    \"isShellCommand\": true,\n    \"args\": [],\n    \"tasks\": [\n        {\n            \"taskName\": \"build\",\n            \"args\": [],\n            \"isBuildCommand\": true,\n            \"problemMatcher\": \"$msCompile\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/EventFeed/Event.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using System;\n\n  public struct Event\n  {\n    public long SequenceNumber { get; }\n    public DateTimeOffset OccurredAt { get; }\n    public string Name { get; }\n    public object Content { get; }\n\n    public Event(\n      long sequenceNumber,\n      DateTimeOffset occurredAt,\n      string name,\n      object content)\n    {\n      this.SequenceNumber = sequenceNumber;\n      this.OccurredAt = occurredAt;\n      this.Name = name;\n      this.Content = content;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/EventFeed/EventStore.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n    using System;\n    using System.Text;\n    using System.Collections.Generic;\n    using System.Data.SqlClient;\n    using System.Linq;\n    using System.Threading.Tasks;\n    using Dapper;\n    using Newtonsoft.Json;\n#if net461\n  using global::EventStore.ClientAPI;\n#endif\n  public class EventStore : IEventStore\n  {\n    private static long currentSequenceNumber = 0;\n    private static readonly IList<Event> database = new List<Event>();\n#if net461\n    private const string connectionString =\n     \"ConnectTo=discover://admin:changeit@127.0.0.1:2112/\";\n    private IEventStoreConnection connection =\n      EventStoreConnection.Create(connectionString);\n      \n    public async Task Raise(string eventName, object content)\n    {\n      await connection.ConnectAsync().ConfigureAwait(false);\n      var contentJson = JsonConvert.SerializeObject(content);\n      var metaDataJson =\n        JsonConvert.SerializeObject(new EventMetadata\n        {\n          OccurredAt = DateTimeOffset.Now,\n          EventName = eventName\n        });\n\n      var eventData = new EventData(\n        Guid.NewGuid(),\n        \"ShoppingCartEvent\",\n        isJson: true,\n        data: Encoding.UTF8.GetBytes(contentJson),\n        metadata: Encoding.UTF8.GetBytes(metaDataJson)\n      );\n\n      await\n        connection.AppendToStreamAsync(\n          \"ShoppingCart\",\n          ExpectedVersion.Any,\n           eventData);\n    }\n    \n    public async Task<IEnumerable<Event>> GetEvents(\n      long firstEventSequenceNumber,\n      long lastEventSequenceNumber)\n    {\n      await connection.ConnectAsync().ConfigureAwait(false);\n\n      var result = await connection.ReadStreamEventsForwardAsync(\n        \"ShoppingCart\",\n        start:(int) firstEventSequenceNumber,\n        count: (int) (lastEventSequenceNumber - firstEventSequenceNumber),\n        resolveLinkTos: false).ConfigureAwait(false);\n\n      return\n        result.Events\n          .Select(ev =>\n            new\n            {\n              Content = JsonConvert.DeserializeObject(\n                Encoding.UTF8.GetString(ev.Event.Data)),\n              Metadata = JsonConvert.DeserializeObject<EventMetadata>(\n                Encoding.UTF8.GetString(ev.Event.Data))\n            })\n          .Select((ev, i) =>\n            new Event(\n              i + firstEventSequenceNumber,\n              ev.Metadata.OccurredAt,\n              ev.Metadata.EventName,\n              ev.Content));\n    }\n        \n    private class EventMetadata\n    {\n      public DateTimeOffset OccurredAt { get; set; }\n      public string EventName { get; set; }\n    }\n#else\n    private string connectionString =\n      @\"Data Source=.\\SQLEXPRESS;Initial Catalog=ShoppingCart;Integrated Security=True\";\n\n    private const string writeEventSql =\n      @\"insert into EventStore(Name, OccurredAt, Content) values (@Name, @OccurredAt, @Content)\";\n    public Task Raise(string eventName, object content)\n    {\n      var jsonContent = JsonConvert.SerializeObject(content);\n      using (var conn = new SqlConnection(connectionString))\n      {\n        return\n          conn.ExecuteAsync(\n            writeEventSql,\n            new\n            {\n              Name = eventName,\n              OccurredAt = DateTimeOffset.Now,\n              Content = jsonContent\n            });\n      }\n    }\n    \n    private const string readEventsSql =\n      @\"select * from EventStore where ID >= @Start and ID <= @End\";\n\n    public async Task<IEnumerable<Event>> GetEvents(\n      long firstEventSequenceNumber,\n      long lastEventSequenceNumber)\n    {\n      using (var conn = new SqlConnection(connectionString))\n      {\n        return (await conn.QueryAsync<dynamic>(\n          readEventsSql,\n          new\n          {\n            Start = firstEventSequenceNumber,\n            End = lastEventSequenceNumber\n          }).ConfigureAwait(false))\n          .Select(row =>\n          {\n            var content = JsonConvert.DeserializeObject(row.Content);\n            return new Event(row.ID, row.OccurredAt, row.Name, content);\n          });\n      }\n    }\n#endif\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/EventFeed/EventsFeedModule.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using Nancy;\n\n  public class EventsFeedModule : NancyModule\n  {\n    public EventsFeedModule(IEventStore eventStore) : base(\"/events\")\n    {\n      Get(\"/\", _ =>\n      {\n        long firstEventSequenceNumber, lastEventSequenceNumber;\n        if (!long.TryParse(this.Request.Query.start.Value, \n          out firstEventSequenceNumber))\n          firstEventSequenceNumber = 0;\n        if (!long.TryParse(this.Request.Query.end.Value, \n          out lastEventSequenceNumber))\n          lastEventSequenceNumber = long.MaxValue;\n\n        return \n          eventStore.GetEvents(\n            firstEventSequenceNumber,\n            lastEventSequenceNumber);\n      });\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/EventFeed/IEventStore.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n  {\n  using System.Collections.Generic;\n  using System.Threading.Tasks;\n    \n  public interface IEventStore\n  {\n    Task<IEnumerable<Event>> GetEvents(long firstEventSequenceNumber, \n      long lastEventSequenceNumber);\n    Task Raise(string eventName, object content);\n  }\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/ICache.cs",
    "content": "namespace ShoppingCart\n{\n    using System;\n    using System.Collections.Concurrent;\n    using System.Collections.Generic;\n\n  public interface ICache  \n  {\n    void Add(string key, object value, TimeSpan ttl);\n    object Get(string productsResource);\n  }\n\n  public class Cache : ICache\n  {\n    private static IDictionary<string, Tuple<DateTimeOffset, object>> cache = new ConcurrentDictionary<string, Tuple<DateTimeOffset, object>>();      \n      \n    public void Add(string key, object value, TimeSpan ttl)\n    {\n      cache[key] = Tuple.Create(DateTimeOffset.UtcNow.Add(ttl), value);\n    }\n\n    public object Get(string productsResource)\n    {\n      Tuple<DateTimeOffset, object> value;\n      if (cache.TryGetValue(productsResource, out value) && value.Item1 > DateTimeOffset.UtcNow)\n        return value;\n      cache.Remove(productsResource);\n      return null;\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/IProductCatalogueClient.cs",
    "content": "﻿namespace ShoppingCart\n{\n  using System.Collections.Generic;\n  using System.Threading.Tasks;\n  using ShoppingCart;\n\n  public interface IProductCatalogueClient\n  {\n    Task<IEnumerable<ShoppingCartItem>>\n      GetShoppingCartItems(int[] productCatalogueIds);\n  }\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/ProductCatalogueClient.cs",
    "content": "﻿namespace ShoppingCart\n{\n    using System;\n    using System.Collections.Generic;\n    using System.Linq;\n    using System.Threading.Tasks;\n    using System.Net.Http;\n    using System.Threading;\n    using Newtonsoft.Json;\n    using Polly;\n    using ShoppingCart;\n    using System.Net.Http.Headers;\n\n    public class ProductCatalogueClient : IProductCatalogueClient\n  {\n    private static Policy exponentialRetryPolicy =\n      Policy\n        .Handle<Exception>()\n        .WaitAndRetryAsync(\n          3, \n          attempt => TimeSpan.FromMilliseconds(100 * Math.Pow(2, attempt)), (ex, _) => Console.WriteLine(ex.ToString()));\n\n    private static string productCatalogueBaseUrl =\n      @\"http://private-05cc8-chapter2productcataloguemicroservice.apiary-mock.com\";\n    private static string getProductPathTemplate =\n      \"/products?productIds=[{0}]\";\n    private readonly ICache cache;  \n    \n    public ProductCatalogueClient(ICache cache)\n    {\n      this.cache = cache;\n    }\n\n    public Task<IEnumerable<ShoppingCartItem>>\n      GetShoppingCartItems(int[] productCatalogueIds) =>\n      exponentialRetryPolicy\n        .ExecuteAsync(() => GetItemsFromCatalogueService(productCatalogueIds));\n\n    private async Task<IEnumerable<ShoppingCartItem>>\n      GetItemsFromCatalogueService(int[] productCatalogueIds)\n    {\n      var response = await\n        RequestProductFromProductCatalogue(productCatalogueIds).ConfigureAwait(false);\n      return await ConvertToShoppingCartItems(response).ConfigureAwait(false);\n    }\n\n    private async Task<HttpResponseMessage> RequestProductFromProductCatalogue(int[] productCatalogueIds)\n    {\n      var productsResource = string.Format(\n        getProductPathTemplate, string.Join(\",\", productCatalogueIds));\n      var response = this.cache.Get(productsResource) as HttpResponseMessage;\n      if (response == null)\n      {\n        using (var httpClient = new HttpClient())\n        {\n          httpClient.BaseAddress = new Uri(productCatalogueBaseUrl);\n          response = await httpClient.GetAsync(productsResource).ConfigureAwait(false);\n          AddToCache(productsResource, response);\n        }\n      }\n      return response;\n    }\n    \n    private void AddToCache(string resource, HttpResponseMessage response)\n    {\n      var cacheHeader = response\n        .Headers\n        .FirstOrDefault(h => h.Key == \"cache-control\");\n      if (string.IsNullOrEmpty(cacheHeader.Key))\n        return;\n      var maxAge =\n        CacheControlHeaderValue.Parse(cacheHeader.Value.ToString())\n          .MaxAge;\n      if (maxAge.HasValue)\n        this.cache.Add(key: resource, value: response, ttl: maxAge.Value);\n    }\n\n    private static async Task<IEnumerable<ShoppingCartItem>> ConvertToShoppingCartItems(HttpResponseMessage response)\n    {\n      response.EnsureSuccessStatusCode();\n      var products = \n        JsonConvert.DeserializeObject<List<ProductCatalogueProduct>>(await response.Content.ReadAsStringAsync().ConfigureAwait(false));\n      return\n        products\n          .Select(p => new ShoppingCartItem(\n            int.Parse(p.ProductId),\n            p.ProductName,\n            p.ProductDescription,\n            p.Price\n        ));\n    }\n\n    private class ProductCatalogueProduct\n    {\n      public string ProductId { get; set; }\n      public string ProductName { get; set; }\n      public string ProductDescription { get; set; }\n      public Money Price { get; set; }\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/Program.cs",
    "content": "using System.IO;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace ShoppingCart\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"ShoppingCart\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/ShoppingCart/IShoppingCartStore.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using System.Threading.Tasks;\n  \n  public interface IShoppingCartStore\n  {\n    Task<ShoppingCart> Get(int userId);\n    Task Save(ShoppingCart shoppingCart);\n  }\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/ShoppingCart/ShoppingCart.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using System.Collections.Generic;\n  using System.Linq;\n  using global::ShoppingCart.EventFeed;\n\n  public class ShoppingCart\n  {\n    private HashSet<ShoppingCartItem> items = new HashSet<ShoppingCartItem>();\n\n    public int UserId { get; }\n    public IEnumerable<ShoppingCartItem> Items { get { return items; } }\n\n    public ShoppingCart(int userId)\n    {\n      this.UserId = userId;\n    }\n\n    public ShoppingCart(int userId, IEnumerable<ShoppingCartItem> items)\n    {\n      this.UserId = userId;\n      foreach (var item in items)\n      {\n        this.items.Add(item);  \n      }\n    }\n    \n    public void AddItems(\n      IEnumerable<ShoppingCartItem> shoppingCartItems,\n      IEventStore eventStore)\n    {\n      foreach (var item in shoppingCartItems)\n        if (this.items.Add(item))\n          eventStore.Raise(\n            \"ShoppingCartItemAdded\",\n            new { UserId, item });\n    }\n\n    public void RemoveItems(\n      int[] productCatalogueIds,\n      IEventStore eventStore)\n    {\n      items.RemoveWhere(i => productCatalogueIds.Contains(i.ProductCatalogueId));\n    }\n  }\n\n  public class ShoppingCartItem\n  {\n    public int ProductCatalogueId { get; }\n    public string ProductName { get; }\n    public string Desscription { get; }\n    public Money Price { get; }\n\n    public ShoppingCartItem(\n      int productCatalogueId,\n      string productName,\n      string description,\n      Money price)\n    {\n      this.ProductCatalogueId = productCatalogueId;\n      this.ProductName = productName;\n      this.Desscription = description;\n      this.Price = price;\n    }\n\n    public override bool Equals(object obj)\n    {\n      if (obj == null || GetType() != obj.GetType())\n      {\n        return false;\n      }\n\n      var that = obj as ShoppingCartItem;\n      return this.ProductCatalogueId.Equals(that.ProductCatalogueId);\n    }\n\n    // override object.GetHashCode\n    public override int GetHashCode()\n    {\n      return this.ProductCatalogueId.GetHashCode();\n    }\n  }\n\n  public class Money\n  {\n    public string Currency { get; }\n    public decimal Amount { get; }\n\n    public Money(string currency, decimal amount)\n    {\n      this.Currency = currency;\n      this.Amount = amount;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/ShoppingCart/ShoppingCartModule.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using EventFeed;\n  using Nancy;\n  using Nancy.ModelBinding;\n\n  public class ShoppingCartModule : NancyModule\n  {\n    public ShoppingCartModule(\n      IShoppingCartStore shoppingCartStore,\n      IProductCatalogueClient productCatalogue,\n      IEventStore eventStore) \n      : base(\"/shoppingcart\")\n    {\n      Get(\"/{userid:int}\", parameters =>\n      {\n        var userId = (int) parameters.userid;\n        return shoppingCartStore.Get(userId);\n      });\n\n      Post(\"/{userid:int}/items\", async parameters =>\n      {\n        var productCatalogueIds = this.Bind<int[]>();\n        var userId = (int) parameters.userid;\n\n        var shoppingCart = await shoppingCartStore.Get(userId).ConfigureAwait(false);\n        var shoppingCartItems = await productCatalogue.GetShoppingCartItems(productCatalogueIds).ConfigureAwait(false);\n        shoppingCart.AddItems(shoppingCartItems, eventStore);\n        shoppingCartStore.Save(shoppingCart);\n\n        return shoppingCart;\n      });\n\n      Delete(\"/{userid:int}/items\", async parameters =>\n      {\n        var productCatalogueIds = this.Bind<int[]>();\n        var userId = (int)parameters.userid;\n\n        var shoppingCart = await shoppingCartStore.Get(userId).ConfigureAwait(false);\n        shoppingCart.RemoveItems(productCatalogueIds, eventStore);\n        shoppingCartStore.Save(shoppingCart);\n\n        return shoppingCart;\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/ShoppingCart/ShoppingCartStore.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n    using System;\n    using System.Collections.Generic;\n    using System.Data.SqlClient;\n    using System.Threading.Tasks;\n    using Dapper;\n\n    public class ShoppingCartStore : IShoppingCartStore\n  {\n    private string connectionString =\n@\"Data Source=.\\SQLEXPRESS;Initial Catalog=ShoppingCart;\nIntegrated Security=True\";\n\n    private const string readItemsSql =\n@\"select * from ShoppingCart, ShoppingCartItems\nwhere ShoppingCartItems.ShoppingCartId = ID\nand ShoppingCart.UserId=@UserId\";\n\n    public async Task<ShoppingCart> Get(int userId)\n    {\n      using (var conn = new SqlConnection(connectionString))\n      {\n        var items = await\n          conn.QueryAsync<ShoppingCartItem>(\n            readItemsSql, \n            new { UserId = userId });\n        return new ShoppingCart(userId, items);\n      }\n    }\n\n      private const string deleteAllForShoppingCartSql=\n @\"delete item from ShoppingCartItems item\ninner join ShoppingCart cart on item.ShoppingCartId = cart.ID\nand cart.UserId=@UserId\";\n \n      private const string addAllForShoppingCartSql=\n@\"insert into ShoppingCartItems \n(ShoppingCartId, ProductCatalogId, ProductName, \nProductDescription, Amount, Currency)\nvalues \n(@ShoppingCartId, @ProductCatalogId, @ProductName,v\n@ProductDescription, @Amount, @Currency)\";\n\n    public async Task Save(ShoppingCart shoppingCart)\n    {\n      using (var conn = new SqlConnection(connectionString))\n      using (var tx = conn.BeginTransaction())\n      {\n        await conn.ExecuteAsync(\n          deleteAllForShoppingCartSql,\n          new { UserId = shoppingCart.UserId },\n          tx).ConfigureAwait(false);\n        await conn.ExecuteAsync(\n          addAllForShoppingCartSql,\n          shoppingCart.Items,\n          tx).ConfigureAwait(false);\n      }\n    }\n\n    }\n}"
  },
  {
    "path": "src/Chapter05/ShoppingCart/ShoppingCart.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>10e4f601-c16b-4936-a7b4-d32d799318d1</ProjectGuid>\n    <RootNamespace>ShoppingCart</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter05/ShoppingCart/Startup.cs",
    "content": "namespace ShoppingCart\n{\n    using Microsoft.AspNetCore.Builder;\n    using Nancy;\n    using Nancy.Configuration;\n    using Nancy.Owin;\n\n    public class Startup\n    {\n        public void Configure(IApplicationBuilder app)\n        {\n            app.UseOwin().UseNancy(opt => opt.Bootstrapper = new TracingBootstrapper());\n        }\n    }    \n    \n    public class TracingBootstrapper : Nancy.DefaultNancyBootstrapper\n    {\n        public override void Configure(INancyEnvironment env)\n        {\n            env.Tracing(enabled: true, displayErrorTraces: true);            \n        }\n    } \n}\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/database-scripts/create-shopping-cart-db.sql",
    "content": "CREATE DATABASE ShoppingCart\nGO\n\nUSE [ShoppingCart]\nGO\n\nCREATE TABLE [dbo].[ShoppingCart](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n  [UserId] [bigint] NOT NULL,\n  CONSTRAINT ShoppingCartUnique UNIQUE([ID], [UserID])\n)\nGO\n\nCREATE INDEX ShoppingCart_UserId \nON [dbo].[ShoppingCart] (UserId)\nGO\n\nCREATE TABLE [dbo].[ShoppingCartItems](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n\t[ShoppingCartId] [int] NOT NULL,\n\t[ProductCatalogId] [bigint] NOT NULL,\n\t[ProductName] [nvarchar](100) NOT NULL,\n\t[ProductDescription] [nvarchar](500) NULL,\n\t[Amount] [int] NOT NULL,\n\t[Currency] [nvarchar](5) NOT NULL\n)\n\nGO\n\nALTER TABLE [dbo].[ShoppingCartItems]  WITH CHECK ADD CONSTRAINT [FK_ShoppingCart] FOREIGN KEY([ShoppingCartId])\nREFERENCES [dbo].[ShoppingCart] ([Id])\nGO\n\nALTER TABLE [dbo].[ShoppingCartItems] CHECK CONSTRAINT [FK_ShoppingCart]\nGO\n\nCREATE INDEX ShoppingCartItems_ShoppingCartId \nON [dbo].[ShoppingCartItems] (ShoppingCartId)\nGO\n\nCREATE TABLE [dbo].[EventStore](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n  [Name] [nvarchar](100)  NOT NULL,\n  [OccurredAt] [datetimeoffset] NOT NULL,\n  [Content][nvarchar](max) NOT NULL\n)\nGO\n\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"Polly\": \"4.2.1\",\n    \"Dapper\": \"1.50.0-rc2a\"\n  },\n  \"runtimes\": {\n    \"win10-x64\": \"\"\n  },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ],\n      \"dependencies\": {\n        \"System.Net.Http\": \"4.0.1\"\n      }\n    },\n    \"net461\": {\n      \"compilationOptions\": {\"define\": [\"net461\"]},\n      \"frameworkAssemblies\": {\n        \"System.Net.Http\": \"4.0.0.0\",\n        \"System.Runtime\": \"4.0.20.0\"\n      },\n      \"dependencies\": {\n        \"EventStore.Client\": \"3.3.1\",\n        \"Microsoft.CSharp\": \"4.0.0\"\n      }\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"HelloMicroservices\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter05/ShoppingCart/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter06/ApiGatewayMock/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter06/ApiGatewayMock/ApiGatewayMock.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>fe109a02-bf1b-46fc-87c8-2a68781ce8a4</ProjectGuid>\n    <RootNamespace>ApiGatewayMock</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter06/ApiGatewayMock/LoyaltyProgramClient.cs",
    "content": "using System;\nusing System.Net.Http;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json;\nusing Polly;\n\nnamespace ApiGatewayMock\n{\n  public class LoyaltyProgramClient\n  {\n    private static Policy exponentialRetryPolicy =\n      Policy\n        .Handle<Exception>()\n        .WaitAndRetryAsync(\n                           3,\n                           attempt => TimeSpan.FromMilliseconds(100*Math.Pow(2, attempt)),\n                           (_, __) => Console.WriteLine(\"retrying...\" + _)\n        );\n\n    private static Policy circuitBreaker =\n      Policy\n        .Handle<Exception>()\n        .CircuitBreaker(5, TimeSpan.FromMinutes(5));\n\n    private string hostName;\n\n    public LoyaltyProgramClient(string loyalProgramMicroserviceHostName)\n    {\n      this.hostName = loyalProgramMicroserviceHostName;\n    }\n\n    public async Task<HttpResponseMessage> QueryUser(int userId)\n    {\n      return await circuitBreaker.ExecuteAsync(() => DoUserQuery(userId));\n    }\n\n    private async Task<HttpResponseMessage> DoUserQuery(int userId)\n    {\n      var userResource = $\"/users/{userId}\";\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri($\"http://{this.hostName}\");\n        var response = await httpClient.GetAsync(userResource);\n        ThrowOnTransientFailure(response);\n        return response;\n      }\n    }\n\n    private static void ThrowOnTransientFailure(HttpResponseMessage response)\n    {\n      if (((int) response.StatusCode) < 200 || ((int) response.StatusCode) > 499)\n        throw new Exception(response.StatusCode.ToString());\n    }\n\n    public async Task<HttpResponseMessage> RegisterUser(LoyaltyProgramUser newUser)\n    {\n      return await exponentialRetryPolicy.ExecuteAsync(() => DoRegisterUser(newUser));\n    }\n\n    private async Task<HttpResponseMessage> DoRegisterUser(LoyaltyProgramUser newUser)\n    {\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri($\"http://{this.hostName}\");\n        var response =\n          await\n          httpClient.PostAsync(\"/users/\",\n                               new StringContent(JsonConvert.SerializeObject(newUser), Encoding.UTF8, \"application/json\"));\n        ThrowOnTransientFailure(response);\n        return response;\n      }\n    }\n\n    public async Task<HttpResponseMessage> UpdateUser(LoyaltyProgramUser user)\n    {\n      return await exponentialRetryPolicy.ExecuteAsync(() => DoUpdateUser(user));\n    }\n\n    private async Task<HttpResponseMessage> DoUpdateUser(LoyaltyProgramUser user)\n    {\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri($\"http://{this.hostName}\");\n        var response =\n          await\n          httpClient.PutAsync($\"/users/{user.Id}\",\n                              new StringContent(JsonConvert.SerializeObject(user), Encoding.UTF8, \"application/json\"));\n        ThrowOnTransientFailure(response);\n        return response;\n      }\n    }\n  }\n\n  public class LoyaltyProgramUser\n  {\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public int LoyaltyPoints { get; set; }\n    public LoyaltyProgramSettings Settings { get; set; }\n  }\n\n  public class LoyaltyProgramSettings\n  {\n    public string[] Interests { get; set; }\n  }\n}\n"
  },
  {
    "path": "src/Chapter06/ApiGatewayMock/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json;\nusing static System.Console;\n\nnamespace ApiGatewayMock\n{\n    public class Program\n    {\n        private LoyaltyProgramClient client;\n\n        public static void Main(string[] arg) => new Program().Main();\n\n        public  void Main()\n        {\n            this.client = new LoyaltyProgramClient(\"localhost:5000\");\n            WriteLine(\"Welcome to the API Gateway Mock.\");\n\n            var cont = true;\n            while (cont)\n            {\n                WriteLine();\n                WriteLine();\n                WriteLine(\"********************\");\n                WriteLine(\"Choose one of:\");\n                WriteLine(\"q <userid> - to query the Loyalty Program Microservice for a user with id <userid>.\");\n                WriteLine(\"r <userid> - to register a user with id <userid> with the Loyalty Program Microservice.\");\n                WriteLine(\"u <userid> <interests> - to update a user with new comman separated interests\");\n                WriteLine(\"exit - to exit\");\n                WriteLine(\"********************\");\n                var cmd = ReadLine();\n                cont = ProcessCommand(cmd);\n            }\n        }\n\n        private bool ProcessCommand(string cmd)\n        {\n            if (\"exit\".Equals(cmd))\n                return false;\n            if (cmd.StartsWith(\"q\"))\n                ProcessUserQuery(cmd);\n            else if (cmd.StartsWith(\"r\"))\n                ProcessUserRegistration(cmd);\n            else if (cmd.StartsWith(\"u\"))\n                ProcessUpdateUser(cmd);\n            else\n              WriteLine(\"Did not understand command :(\");\n            return true;\n        }\n\n        private void ProcessUserQuery(string cmd)\n        {\n            int userId;\n            if (!int.TryParse(cmd.Substring(1), out userId))\n                WriteLine(\"Please specify user id as an int\");\n            else\n            {\n                var response = this.client.QueryUser(userId).Result;\n                PrettyPrintResponse(response);\n            }\n        }\n\n        private void ProcessUserRegistration(string cmd)\n        {\n            var newUser = new LoyaltyProgramUser { Name = cmd.Substring(1).Trim() };\n            var response = this.client.RegisterUser(newUser).Result;\n            PrettyPrintResponse(response);\n        }\n\n        private static async void PrettyPrintResponse(HttpResponseMessage response)\n        {\n            WriteLine(\"Status code: \" + response?.StatusCode.ToString() ?? \"command failed\");\n            WriteLine(\"Headers: \" + response?.Headers.Aggregate(\"\", (acc, h) => acc + \"\\n\\t\" + h.Key + \": \" + h.Value) ?? \"\");\n            WriteLine(\"Body: \" + await response?.Content.ReadAsStringAsync() ?? \"\");\n        }\n        \n        private async void ProcessUpdateUser(string cmd)\n        {\n            int userId;\n            if (!int.TryParse(cmd.Split(' ').Skip(1).First(), out userId))\n              WriteLine(\"Plaese speciffy user id as an int\");\n            else\n            {\n              var response = this.client.QueryUser(userId).Result;\n              if (response.StatusCode == System.Net.HttpStatusCode.OK)\n              {\n                var user = JsonConvert.DeserializeObject<LoyaltyProgramUser>(await response.Content.ReadAsStringAsync());\n                var newInterests = cmd.Substring(cmd.IndexOf(' ', 2)).Split(',').Select(i => i.Trim());\n                user.Settings = \n                  new LoyaltyProgramSettings \n                  { \n                    Interests =\n                      user.Settings?.Interests.Union(newInterests).ToArray() \n                      ??  newInterests.ToArray()\n                   };\n                 PrettyPrintResponse(this.client.UpdateUser(user).Result);\n              }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter06/ApiGatewayMock/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n  \"buildOptions\": {\n    \"emitEntryPoint\": true\n  },\n\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"type\": \"platform\",\n      \"version\": \"1.0.0\"\n    },\n    \"Newtonsoft.Json\": \"8.0.3\",\n    \"Polly\": \"4.2.1\",\n    \"System.Net.Http\": \"4.0.1\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": \"dnxcore50\"\n    }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"ApiGatewayMock\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter06/Ch6.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25123.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgram\", \"LoyaltyProgram\\LoyaltyProgram.xproj\", \"{4BED3C45-E8C3-4345-A08F-249A39A256EB}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"ApiGatewayMock\", \"ApiGatewayMock\\ApiGatewayMock.xproj\", \"{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgramEventConsumer\", \"LoyaltyProgramEventConsumer\\LoyaltyProgramEventConsumer.xproj\", \"{47349717-585A-43EE-96E8-7D5249CB431D}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/Bootstrapper.cs",
    "content": "namespace LoyaltyProgram\n{\n  using System;\n  using Nancy;\n  using Nancy.Bootstrapper;\n  using Nancy.TinyIoc;\n\n  public class Bootstrapper : DefaultNancyBootstrapper\n  {\n    protected override Func<ITypeCatalog, NancyInternalConfiguration> InternalConfiguration\n     => NancyInternalConfiguration.WithOverrides(builder => builder.StatusCodeHandlers.Clear());\n\n    protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)\n    {\n      pipelines.OnError += (ctx, ex) =>\n      {\n        // write to central log store\n        return null;\n      };\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/LoyaltyProgram.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>4bed3c45-e8c3-4345-a08f-249a39a256eb</ProjectGuid>\n    <RootNamespace>LoyaltyProgram</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace LoyaltyProgram\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"LoyaltyProgram\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/Startup.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace LoyaltyProgram\n{\n    public class Startup\n    {\n        // This method gets called by the runtime. Use this method to add services to the container.\n        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940\n        public void ConfigureServices(IServiceCollection services)\n        {\n        }\n\n        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n        public void Configure(IApplicationBuilder app)\n        {\n            app.Run(async (context) =>\n            {\n                await context.Response.WriteAsync(\"Hello World!\");\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/UsersModule.cs",
    "content": "using System.Collections.Generic;\nusing Nancy;\nusing Nancy.ModelBinding;\n\nnamespace LoyaltyProgram\n{\n  public class UsersModule : NancyModule\n  {\n    private static IDictionary<int, LoyaltyProgramUser> registerUsers =\n      new Dictionary<int, LoyaltyProgramUser>();\n\n    public UsersModule() : base(\"/users\")\n    {\n      Get(\"/\", _ => registerUsers.Values);\n\n      Get(\"/{userId:int}\", parameters =>\n      {\n        int userId = parameters.userId;\n        if (registerUsers.ContainsKey(userId))\n          return registerUsers[userId];\n        else\n          return HttpStatusCode.NotFound;\n      });\n\n      Post(\"/\", _ =>\n      {\n        var newUser = this.Bind<LoyaltyProgramUser>();\n        this.AddRegisteredUser(newUser);\n        return this.CreatedResponse(newUser);\n      });\n\n      Put(\"/{userId:int}\", parameters =>\n      {\n        int userId = parameters.userId;\n        var updatedUser = this.Bind<LoyaltyProgramUser>();\n        registerUsers[userId] = updatedUser;\n        return updatedUser;\n      });\n    }\n\n    private dynamic CreatedResponse(LoyaltyProgramUser newUser)\n    {\n      return\n          this.Negotiate\n              .WithStatusCode(HttpStatusCode.Created)\n              .WithHeader(\"Location\", this.Request.Url.SiteBase + \"/users/\" + newUser.Id)\n              .WithModel(newUser);\n    }\n\n    private void AddRegisteredUser(LoyaltyProgramUser newUser)\n    {\n      var userId = registerUsers.Count;\n      newUser.Id = userId;\n      registerUsers[userId] = newUser;\n    }\n  }\n\n  public class LoyaltyProgramUser\n  {\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public int LoyaltyPoints { get; set; }\n    public LoyaltyProgramSettings Settings { get; set; }\n  }\n\n  public class LoyaltyProgramSettings\n  {\n    public string[] Interests { get; set; }\n  }\n}\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/YamlSerializerDeserializer.cs",
    "content": "namespace LoyaltyProgram\n{\n   using System;\n   using System.Collections.Generic;\n   using System.IO;\n   using Nancy;\n   using Nancy.ModelBinding;\n   using Nancy.Responses.Negotiation;\n   using YamlDotNet.Serialization;\n\n    public class YamlBodyDeserializer : IBodyDeserializer\n    {\n        public bool CanDeserialize(MediaRange mediaRange, BindingContext context)\n          => mediaRange.Subtype.ToString().EndsWith(\"yaml\");\n\n        public object Deserialize(MediaRange mediaRange, Stream bodyStream, BindingContext context)\n        {\n          var yamlDeserializer = new Deserializer();\n          var reader = new StreamReader(bodyStream);\n          return yamlDeserializer.Deserialize(reader, context.DestinationType);\n        }\n    }\n\n    public class YamlBodySerializer : IResponseProcessor\n    {\n        public IEnumerable<Tuple<string, MediaRange>> ExtensionMappings\n        {\n            get\n            {\n              yield return new Tuple<string, MediaRange>(\"yaml\", new MediaRange(\"application/yaml\"));\n            }\n        }\n\n        public ProcessorMatch CanProcess(MediaRange requestedMediaRange, dynamic model, NancyContext context)\n          =>\n            requestedMediaRange.Subtype.ToString().EndsWith(\"yaml\") \n            ? new ProcessorMatch { ModelResult = MatchResult.DontCare, RequestedContentTypeResult = MatchResult.NonExactMatch}\n            : ProcessorMatch.None;         \n\n        public Response Process(MediaRange requestedMediaRange, dynamic model, NancyContext context)\n          =>\n            new Response\n            {\n              Contents = stream =>\n              {\n                  var yamlSerializer = new Serializer();\n                  var streamWriter = new StreamWriter(stream);\n                  yamlSerializer.Serialize(streamWriter, model);\n                  streamWriter.Flush();\n              },\n              ContentType = \"application/yaml\"\n            };      \n    }\n}"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"YamlDotNet\": \"3.8.0-pre233\"\n  },\n\n  \"tools\": {\n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": {\n      \"version\": \"1.0.0-preview1-final\",\n      \"imports\": \"portable-net45+win8+dnxcore50\"\n    }\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgram\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgram/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgramEventConsumer/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter06/LoyaltyProgramEventConsumer/LoyaltyProgramEventConsumer.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>47349717-585a-43ee-96e8-7d5249cb431d</ProjectGuid>\n    <RootNamespace>LoyaltyProgramEventConsumer</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter06/LoyaltyProgramEventConsumer/Program.cs",
    "content": "using static System.Console;\n\nnamespace LoyaltyProgramEventConsumer\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Net;\n  using System.Net.Http;\n  using System.ServiceProcess;\n  using System.Threading.Tasks;\n  using System.Timers;\n  using Newtonsoft.Json;\n\n  public class EventSubscriber\n  {\n    private readonly string loyaltyProgramHost;\n    private long start = 0, chunkSize = 100;\n    private readonly Timer timer;\n\n    public EventSubscriber(string loyaltyProgramHost)\n    {\n      WriteLine(\"created\");\n      this.loyaltyProgramHost = loyaltyProgramHost;\n      this.timer = new Timer(10*1000);\n      this.timer.AutoReset = false;\n      this.timer.Elapsed += (_, __) => SubscriptionCycleCallback().Wait();\n    }\n\n    private async Task SubscriptionCycleCallback()\n    {\n      var response = await ReadEvents().ConfigureAwait(false);\n      if (response.StatusCode == HttpStatusCode.OK)\n        HandleEvents(await response.Content.ReadAsStringAsync().ConfigureAwait(false));\n      this.timer.Start();\n    }\n\n    private async Task<HttpResponseMessage> ReadEvents()\n    {\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri($\"http://{this.loyaltyProgramHost}\");\n        var resource = $\"/events/?start={this.start}&end={this.start + this.chunkSize}\";\n        var response = await httpClient.GetAsync(resource).ConfigureAwait(false);\n        PrettyPrintResponse(response);\n        return response;\n      }\n    }\n\n    private void HandleEvents(string content)\n    {\n      WriteLine(\"Handling events\");\n      var events = JsonConvert.DeserializeObject<IEnumerable<Event>>(content);\n      WriteLine(events);\n      WriteLine(events.Count());\n      foreach (var ev in events)\n      {\n        WriteLine(ev.Content);\n        dynamic eventData = ev.Content;\n        WriteLine(\"product name from data: \" + (string) eventData.item.productName);\n        this.start = Math.Max(this.start, ev.SequenceNumber + 1);\n      }\n    }\n\n\n    public void Start()\n    {\n      this.timer.Start();\n    }\n\n    public void Stop()\n    {\n      this.timer.Stop();\n    }\n\n    private static async void PrettyPrintResponse(HttpResponseMessage response)\n    {\n      WriteLine(\"Status code: \" + response?.StatusCode.ToString() ?? \"command failed\");\n      WriteLine(\"Headers: \" + response?.Headers.Aggregate(\"\", (acc, h) => acc + \"\\n\\t\" + h.Key + \": \" + h.Value) ?? \"\");\n      WriteLine(\"Body: \" + await response?.Content.ReadAsStringAsync() ?? \"\");\n    }\n  }\n\n  public struct Event\n  {\n    public long SequenceNumber { get; set; }\n    public string Name { get; set; }\n    public object Content { get; set; }\n  } \n   \n    public class Program : ServiceBase\n    {\n        private EventSubscriber subscriber;\n\n      public static void Main(string[] args) => new Program().Main();\n\n        public void Main()\n        {\n          this.subscriber = new EventSubscriber(\"localhost:5000\");\n          //Run(this);\n          OnStart(null);\n          ReadLine();\n        }\n \n        protected override void OnStart(string[] args)\n        {\n          this.subscriber.Start();\n        }\n \n        protected override void OnStop()\n        {\n          this.subscriber.Stop();\n        }\n    }\n}"
  },
  {
    "path": "src/Chapter06/LoyaltyProgramEventConsumer/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n  \"buildOptions\": {\n    \"emitEntryPoint\": true\n  },\n\n  \"dependencies\": {\n    \"Newtonsoft.Json\": \"8.0.3\",\n    \"System.ServiceProcess.ServiceController\": \"4.1.0\",\n    \"System.Net.Http\": \"4.1.0\"\n  },\n\n  \"frameworks\": {\n    \"net461\": { }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgramEventConsumer\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/.idea.Ch7/riderModule.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"RIDER_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\">\n    <content url=\"file://$MODULE_DIR$/..\">\n      <sourceFolder url=\"file://$MODULE_DIR$/..\" isTestSource=\"false\" />\n    </content>\n    <content url=\"file://C:/projects/Nancy/src/Nancy.Authentication.Forms\">\n      <sourceFolder url=\"file://C:/projects/Nancy/src/Nancy.Authentication.Forms\" isTestSource=\"false\" />\n    </content>\n    <content url=\"file://C:/projects/Nancy/src/Nancy.Hosting.Self\">\n      <sourceFolder url=\"file://C:/projects/Nancy/src/Nancy.Hosting.Self\" isTestSource=\"false\" />\n    </content>\n    <content url=\"file://C:/projects/Nancy/src/Nancy.Testing\">\n      <sourceFolder url=\"file://C:/projects/Nancy/src/Nancy.Testing\" isTestSource=\"false\" />\n    </content>\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n  </component>\n</module>"
  },
  {
    "path": "src/Chapter07/Ch7.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25123.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgram\", \"LoyaltyProgram\\LoyaltyProgram.xproj\", \"{4BED3C45-E8C3-4345-A08F-249A39A256EB}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgramEventConsumer\", \"LoyaltyProgramEventConsumer\\LoyaltyProgramEventConsumer.xproj\", \"{47349717-585A-43EE-96E8-7D5249CB431D}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgramUnitTests\", \"LoyaltyProgramUnitTests\\LoyaltyProgramUnitTests.xproj\", \"{DF4D91A9-C2B2-47A1-B3F5-74D3A03E7AAF}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgramIntegrationTest\", \"LoyaltyProgramIntegrationTest\\LoyaltyProgramIntegrationTest.xproj\", \"{4ADB7532-5BBB-4A6F-9044-6095427DB0E6}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{87C7C329-1824-4AC7-AF25-3D06068A01F6}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{47349717-585A-43EE-96E8-7D5249CB431D}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{DF4D91A9-C2B2-47A1-B3F5-74D3A03E7AAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{DF4D91A9-C2B2-47A1-B3F5-74D3A03E7AAF}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{DF4D91A9-C2B2-47A1-B3F5-74D3A03E7AAF}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{DF4D91A9-C2B2-47A1-B3F5-74D3A03E7AAF}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{4ADB7532-5BBB-4A6F-9044-6095427DB0E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{4ADB7532-5BBB-4A6F-9044-6095427DB0E6}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{4ADB7532-5BBB-4A6F-9044-6095427DB0E6}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{4ADB7532-5BBB-4A6F-9044-6095427DB0E6}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/Bootstrapper.cs",
    "content": "namespace LoyaltyProgram\n{\n  using System;\n  using Nancy;\n  using Nancy.Bootstrapper;\n  using Nancy.TinyIoc;\n\n  public class Bootstrapper : DefaultNancyBootstrapper\n  {\n    protected override Func<ITypeCatalog, NancyInternalConfiguration> InternalConfiguration\n     => NancyInternalConfiguration.WithOverrides(builder => builder.StatusCodeHandlers.Clear());\n\n    protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)\n    {\n      pipelines.OnError += (ctx, ex) =>\n      {\n        // write to central log store\n        return null;\n      };\n    }\n\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/EventFeed/Event.cs",
    "content": "﻿namespace LoyaltyProgram.EventFeed\n{\n  using System;\n\n  public struct Event\n  {\n    public long SequenceNumber { get; }\n    public DateTimeOffset OccuredAt { get; }\n    public string Name { get; }\n    public object Content { get; }\n\n    public Event(\n      long sequenceNumber,\n      DateTimeOffset occuredAt,\n      string name,\n      object content)\n    {\n      this.SequenceNumber = sequenceNumber;\n      this.OccuredAt = occuredAt;\n      this.Name = name;\n      this.Content = content;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/EventFeed/EventStore.cs",
    "content": "﻿namespace LoyaltyProgram.EventFeed\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Threading;\n\n  public class EventStore : IEventStore\n  {\n    private static long currentSequenceNumber = 0;\n    private static readonly IList<Event> database = new List<Event>();\n\n    public IEnumerable<Event> GetEvents(\n      long firstEventSequenceNumber,\n      long lastEventSequenceNumber) \n      => database\n          .Where(e =>\n            e.SequenceNumber >= firstEventSequenceNumber &&\n            e.SequenceNumber <= lastEventSequenceNumber)\n          .OrderBy(e => e.SequenceNumber);\n\n    public void Raise(string eventName, object content)\n    {\n      var seqNumber = Interlocked.Increment(ref currentSequenceNumber);\n      database.Add(\n        new Event(\n          seqNumber,\n          DateTimeOffset.UtcNow,\n          eventName,\n          content));\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/EventFeed/EventsFeedModule.cs",
    "content": "﻿namespace LoyaltyProgram.EventFeed\n{\n  using Nancy;\n\n  public class EventsFeedModule : NancyModule\n  {\n    public EventsFeedModule(IEventStore eventStore) : base(\"/events\")\n    {\n      Get(\"/\", _ =>\n      {\n        long firstEventSequenceNumber, lastEventSequenceNumber;\n        if (!long.TryParse(this.Request.Query.start.Value, \n          out firstEventSequenceNumber))\n          firstEventSequenceNumber = 0;\n        if (!long.TryParse(this.Request.Query.end.Value, \n          out lastEventSequenceNumber))\n          lastEventSequenceNumber = 50;\n\n        return \n          eventStore.GetEvents(\n            firstEventSequenceNumber,\n            lastEventSequenceNumber);\n      });\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/EventFeed/IEventStore.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace LoyaltyProgram.EventFeed\n{\n  public interface IEventStore\n  {\n    IEnumerable<Event> GetEvents(long firstEventSequenceNumber, long lastEventSequenceNumber);\n    void Raise(string eventName, object content);\n  }\n}"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/LoyaltyProgram.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>4bed3c45-e8c3-4345-a08f-249a39a256eb</ProjectGuid>\n    <RootNamespace>LoyaltyProgram</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/Program.cs",
    "content": "namespace LoyaltyProgram\n{\n  using System.IO;\n  using Microsoft.AspNetCore.Hosting;\n\n  public class Program\n  {\n    public static void Main(string[] args)\n    {\n      var host = new WebHostBuilder()\n        .UseKestrel()\n        .UseContentRoot(Directory.GetCurrentDirectory())\n        .UseIISIntegration()\n        .UseStartup<Startup>()\n        .Build();\n\n      host.Run();\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"LoyaltyProgram\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/Startup.cs",
    "content": "namespace LoyaltyProgram\n{\n  using Microsoft.AspNetCore.Builder;\n  using Nancy.Owin;\n\n  public class Startup\n  {\n    public void Configure(IApplicationBuilder app)\n    {\n      app.UseOwin(buildFunc => buildFunc.UseNancy());\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/UsersModule.cs",
    "content": "using System.Collections.Generic;\nusing Nancy;\nusing Nancy.ModelBinding;\n\nnamespace LoyaltyProgram\n{\n  public class UsersModule : NancyModule\n  {\n    private static IDictionary<int, LoyaltyProgramUser> registerUsers =\n      new Dictionary<int, LoyaltyProgramUser>();\n\n    public UsersModule() : base(\"/users\")\n    {\n      Get(\"/\", _ => registerUsers.Values);\n\n      Get(\"/{userId:int}\", parameters =>\n      {\n        int userId = parameters.userId;\n        if (registerUsers.ContainsKey(userId))\n          return registerUsers[userId];\n        else\n          return HttpStatusCode.NotFound;\n      });\n\n      Post(\"/\", _ =>\n      {\n        var newUser = this.Bind<LoyaltyProgramUser>();\n        this.AddRegisteredUser(newUser);\n        return this.CreatedResponse(newUser);\n      });\n\n      Put(\"/{userId:int}\", parameters =>\n      {\n        int userId = parameters.userId;\n        var updatedUser = this.Bind<LoyaltyProgramUser>();\n        registerUsers[userId] = updatedUser;\n        return updatedUser;\n      });\n    }\n\n    private dynamic CreatedResponse(LoyaltyProgramUser newUser)\n    {\n      return\n          this.Negotiate\n              .WithStatusCode(HttpStatusCode.Created)\n              .WithHeader(\"Location\", this.Request.Url.SiteBase + \"/users/\" + newUser.Id)\n              .WithModel(newUser);\n    }\n\n    private void AddRegisteredUser(LoyaltyProgramUser newUser)\n    {\n      var userId = registerUsers.Count;\n      newUser.Id = userId;\n      registerUsers[userId] = newUser;\n    }\n  }\n\n  public class LoyaltyProgramUser\n  {\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public int LoyaltyPoints { get; set; }\n    public LoyaltyProgramSettings Settings { get; set; }\n  }\n\n  public class LoyaltyProgramSettings\n  {\n    public string[] Interests { get; set; }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/YamlSerializerDeserializer.cs",
    "content": "namespace LoyaltyProgram\n{\n   using System;\n   using System.Collections.Generic;\n   using System.IO;\n   using Nancy;\n   using Nancy.ModelBinding;\n   using Nancy.Responses.Negotiation;\n   using YamlDotNet.Serialization;\n\n    public class YamlBodyDeserializer : IBodyDeserializer\n    {\n        public bool CanDeserialize(MediaRange mediaRange, BindingContext context)\n          => mediaRange.Subtype.ToString().EndsWith(\"yaml\");\n\n        public object Deserialize(MediaRange mediaRange, Stream bodyStream, BindingContext context)\n        {\n          var yamlDeserializer = new Deserializer();\n          var reader = new StreamReader(bodyStream);\n          return yamlDeserializer.Deserialize(reader, context.DestinationType);\n        }\n    }\n\n    public class YamlBodySerializer : IResponseProcessor\n    {\n        public IEnumerable<Tuple<string, MediaRange>> ExtensionMappings\n        {\n            get\n            {\n              yield return new Tuple<string, MediaRange>(\"yaml\", new MediaRange(\"application/yaml\"));\n            }\n        }\n\n        public ProcessorMatch CanProcess(MediaRange requestedMediaRange, dynamic model, NancyContext context)\n          =>\n            requestedMediaRange.Subtype.ToString().EndsWith(\"yaml\") \n            ? new ProcessorMatch { ModelResult = MatchResult.DontCare, RequestedContentTypeResult = MatchResult.NonExactMatch}\n            : ProcessorMatch.None;         \n\n        public Response Process(MediaRange requestedMediaRange, dynamic model, NancyContext context)\n          =>\n            new Response\n            {\n              Contents = stream =>\n              {\n                  var yamlSerializer = new Serializer();\n                  var streamWriter = new StreamWriter(stream);\n                  yamlSerializer.Serialize(streamWriter, model);\n                  streamWriter.Flush();\n              },\n              ContentType = \"application/yaml\"\n            };      \n    }\n}"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"YamlDotNet\": \"3.8.0-pre233\"\n  },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n  \n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgram\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgram/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramEventConsumer/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramEventConsumer/LoyaltyProgramEventConsumer.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>47349717-585a-43ee-96e8-7d5249cb431d</ProjectGuid>\n    <RootNamespace>LoyaltyProgramEventConsumer</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramEventConsumer/Program.cs",
    "content": "using static System.Console;\n\nnamespace LoyaltyProgramEventConsumer\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Net;\n  using System.Net.Http;\n  using System.ServiceProcess;\n  using System.Threading.Tasks;\n  using System.Timers;\n  using Newtonsoft.Json;\n\n  public class EventSubscriber\n  {\n    private readonly string loyaltyProgramHost;\n    private readonly string notificationHost;\n    private long start = 0, chunkSize = 100;\n    private readonly Timer timer;\n\n    public EventSubscriber(string loyaltyProgramHost)\n    {\n      WriteLine(\"created\");\n      this.loyaltyProgramHost = loyaltyProgramHost;\n      this.notificationHost = loyaltyProgramHost;\n      this.timer = new Timer(10*1000);\n      this.timer.AutoReset = false;\n      this.timer.Elapsed += (_, __) => SubscriptionCycleCallback().Wait();\n    }\n\n    private async Task SubscriptionCycleCallback()\n    {\n      var response = await ReadEvents();\n      if (response.StatusCode == HttpStatusCode.OK)\n        await HandleEvents(await response.Content.ReadAsStringAsync());\n      this.timer.Start();\n    }\n\n    private async Task<HttpResponseMessage> ReadEvents()\n    {\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri($\"http://{this.loyaltyProgramHost}\");\n        var response = await httpClient.GetAsync($\"/events/?start={this.start}&end={this.start + this.chunkSize}\").ConfigureAwait(false);\n        PrettyPrintResponse(response);\n        return response;\n      }\n    }\n\n    private async Task HandleEvents(string content)\n    {\n      WriteLine(\"Handling events\");\n      var events = JsonConvert.DeserializeObject<IEnumerable<Event>>(content);\n      WriteLine(events);\n      WriteLine(events.Count());\n\n      var results = new List<Task>();\n      foreach (var ev in events)\n      {\n        WriteLine(ev.Content);\n        dynamic eventData = ev.Content;\n        WriteLine(\"product name from data: \" + (string) eventData.item.productName);\n        this.start = Math.Max(this.start, ev.SequenceNumber + 1);\n\n        using (var httpClient = new HttpClient())\n        {\n          WriteLine(\"notifying\");\n          httpClient.BaseAddress = new Uri($\"http://{this.notificationHost}\");\n          var response = await httpClient.GetAsync(\"/notify\").ConfigureAwait(false);\n          PrettyPrintResponse(response);\n//          results.Add(httpClient.GetAsync(\"/notify\"));\n        }\n      }\n//      await Task.WhenAll(results).ConfigureAwait(false);\n      WriteLine(\"done notifying\");\n    }\n\n\n    public void Start()\n    {\n      this.timer.Start();\n    }\n\n    public void Stop()\n    {\n      this.timer.Stop();\n    }\n\n    private static async void PrettyPrintResponse(HttpResponseMessage response)\n    {\n      WriteLine(\"Status code: \" + response?.StatusCode.ToString() ?? \"command failed\");\n      WriteLine(\"Headers: \" + response?.Headers.Aggregate(\"\", (acc, h) => acc + \"\\n\\t\" + h.Key + \": \" + h.Value) ?? \"\");\n      WriteLine(\"Body: \" + await response?.Content.ReadAsStringAsync() ?? \"\");\n    }\n  }\n\n  public struct Event\n  {\n    public long SequenceNumber { get; set; }\n    public string Name { get; set; }\n    public object Content { get; set; }\n  }\n\n  public class Program : ServiceBase\n  {\n    private EventSubscriber subscriber;\n\n    public static void Main(string[] args) => new Program().Entry(args);\n\n    public void Entry(string[] args)\n    {\n      this.subscriber = new EventSubscriber(args[0]);\n      if (args.Length >= 2 && args[1].Equals(\"--service\"))\n        Run(this);\n      else\n        OnStart(null);\n      ReadLine();\n    }\n\n    protected override void OnStart(string[] args)\n    {\n      this.subscriber.Start();\n    }\n\n    protected override void OnStop()\n    {\n      this.subscriber.Stop();\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramEventConsumer/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n  \"buildOptions\": {\n    \"emitEntryPoint\": true\n  },\n\n  \"dependencies\": {\n    \"Newtonsoft.Json\": \"8.0.3\",\n    \"System.ServiceProcess.ServiceController\": \"4.1.0-rc2-24027\",\n    \"System.Net.Http\": \"4.1.0\"\n  },\n\n  \"frameworks\": {\n    \"net461\": { }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgramEventConsumer\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramIntegrationTest/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramIntegrationTest/FakeEndpoints.cs",
    "content": "namespace LoyaltyProgramIntegrationTests\n{\n  using System;\n  using System.Threading;\n    using Microsoft.AspNetCore.Builder;\n  using Nancy;\n  using Nancy.Owin;\n\n    public class FakeEventFeed : NancyModule\n    {\n      public static AutoResetEvent polled = new AutoResetEvent(initialState: false);\n      \n      public FakeEventFeed()\n      {\n        this.Get(\"/events\", _ => \n        {\n          polled.Set();\n          return Response.AsJson(new [] { new { SequenceNumber = 1, Name= \"baz\", Content = new { OfferName = \"foo\", Desciption = \"bar\", item = new { ProductName = \"name\" }}}});\n        });\n      }\n    }\n    \n    public class FakeNotifications : NancyModule\n    {\n      public static bool NotificationWasSent = false;\n      public FakeNotifications()\n      {\n        this.Get(\"/notify\", _ => \n        {\n          NotificationWasSent = true;\n          Console.WriteLine(\"notified\");\n          return 200;\n        }); \n      }\n    }\n\n  public class FakeStartup\n  {  \n    public void Configure(IApplicationBuilder app)\n    {\n      app.UseOwin(buildFunc => buildFunc.UseNancy());\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramIntegrationTest/LoyaltyProgramIntegrationTest.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>4adb7532-5bbb-4a6f-9044-6095427db0e6</ProjectGuid>\n    <RootNamespace>LoyaltyProgramIntegrationTest</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramIntegrationTest/RegisterUserAndGetNotificationScenario.cs",
    "content": "namespace LoyaltyProgramIntegrationTests\n{\n    using System;\n    using System.Diagnostics;\n    using System.IO;\n    using System.Net;\n    using System.Net.Http;\n    using System.Text;\n    using System.Threading;\n    using System.Threading.Tasks;\n    using Microsoft.AspNetCore.Hosting;\n    using Newtonsoft.Json;\n    using Xunit;\n\n  public class RegisterUserAndGetNotification : IDisposable\n  {\n    private IWebHost hostForFakeEndpoints;\n    private Process eventConsumer;\n    private Process api;\n    private Thread thread;\n\n    public RegisterUserAndGetNotification()\n    {\n      StartLoayaltyProgram();\n      StartFakeEndpoints();\n    }\n\n    private void StartFakeEndpoints()\n    {\n      this.hostForFakeEndpoints = new WebHostBuilder()\n        .UseKestrel()\n        .UseContentRoot(Directory.GetCurrentDirectory())\n        .UseStartup<FakeStartup>()\n        .UseUrls(\"http://localhost:5001\")\n        .Build();\n\n      this.thread = new Thread(() => this.hostForFakeEndpoints.Run());\n      this.thread.Start();\n    }\n\n    private void StartLoayaltyProgram()\n    {\n      StartEventConsumer();\n      StartLoyaltyProgramApi();\n    }\n\n    private void StartLoyaltyProgramApi()\n    {\n      var apiInfo = new ProcessStartInfo(\"dotnet.exe\")\n      {\n        Arguments = \"run\",\n        WorkingDirectory = \"../LoyaltyProgram\"\n      };\n      this.api = Process.Start(apiInfo);\n    }\n\n    private void StartEventConsumer()\n    {\n      var eventConsumerInfo = new ProcessStartInfo(\"dotnet.exe\")\n      {\n        Arguments = \"run localhost:5001\",\n        WorkingDirectory = \"../LoyaltyProgramEventConsumer\"   \n      };\n      this.eventConsumer = Process.Start(eventConsumerInfo);\n    }\n\n    [Fact]\n    public void Scenario()\n    {\n      RegisterNewUser();\n      WaitForConsumerToReadSpeciallOffersEvents();\n      AssertNotificationWassent();\n    }\n\n    private async Task RegisterNewUser()\n    {\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri(\"http://localhost:5000\");\n        var response = await\n          httpClient.PostAsync(\n            \"/users/\",\n            new StringContent(\n              JsonConvert.SerializeObject(new LoyaltyProgramUser()),\n              Encoding.UTF8,\n              \"application/json\")).ConfigureAwait(false);\n        Assert.Equal(HttpStatusCode.Created, response.StatusCode);\n        Console.WriteLine(\"registered users\");\n      }\n    }\n\n    private static void AssertNotificationWassent()\n    {\n      Assert.True(FakeNotifications.NotificationWasSent);\n    }\n\n    private static void WaitForConsumerToReadSpeciallOffersEvents()\n    {\n      Console.WriteLine(\"waiting for event poll ....\");\n      Assert.True(FakeEventFeed.polled.WaitOne(30000));\n      Console.WriteLine(\"got poll ....\");\n      Thread.Sleep(1000);\n      Console.WriteLine(\"waited for notification ....\");\n    }\n\n    public void Dispose()\n    {\n      Console.WriteLine(\"disposing...\");\n      this.eventConsumer.Dispose();\n      this.api.Dispose();\n      //this.hostForFakeEndpoints.Dispose();\n      Console.WriteLine(\"disposed...\");\n    }\n  }\n  \n  public class LoyaltyProgramUser\n  {\n    public int Id { get; set; }\n    public string Name { get; set;  }\n    public int LoyaltyPoints { get; set;  }\n    public LoyaltyProgramSettings Settings { get; set; }\n  }\n\n  public class LoyaltyProgramSettings\n  {\n    public string[] Interests { get; set; }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramIntegrationTest/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n\n  \"buildOptions\": {\n    \"preserveCompilationContext\": true\n  },\n\n  \"dependencies\": {\n    \"dotnet-test-xunit\": \"2.2.0-preview2-build1029\",\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"xunit\": \"2.1.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"LoyaltyProgram\": { \"target\": \"project\" }\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"testRunner\": \"xunit\",\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgramIntegrationTest\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramUnitTests/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramUnitTests/EventFeed_should.cs",
    "content": "namespace LoyaltyProgramUnitTests\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Threading.Tasks;\n  using LoyaltyProgram.EventFeed;\n  using Nancy;\n  using Nancy.Testing;\n  using Xunit;\n\n  public class EventFeed_should\n  {\n    private Browser sut;\n\n    public EventFeed_should()\n    {\n      this.sut = new Browser(\n        with =>\n        with.Module<EventsFeedModule>().Dependency<IEventStore>(typeof (FakeEventStore)),\n        withDefault => withDefault.Accept(\"application/json\"));\n    }\n\n    [Fact]\n    public async Task return_events_when_from_event_store()\n    {\n      var actual = await sut.Get(\"/events/\",\n                                 with =>\n                                 {\n                                   with.Query(\"start\", \"0\");\n                                   with.Query(\"end\", \"100\");\n                                 });\n\n      Assert.Equal(HttpStatusCode.OK, actual.StatusCode);\n      Assert.StartsWith(\"application/json\", actual.ContentType);\n      //Assert.Equal(100, actual.Body.DeserializeJson<IEnumerable<Event>>().Count());\n    }\n\n    [Fact]\n    public async Task return_empty_response_when_there_are_no_more_events()\n    {\n      var actual = await sut.Get(\"/events/\",\n                                 with =>\n                                 {\n                                   with.Query(\"start\", \"200\");\n                                   with.Query(\"end\", \"300\");\n                                 });\n\n      Assert.Empty(actual.Body.DeserializeJson<IEnumerable<Event>>());\n    }\n  }\n\n\n  public class FakeEventStore : IEventStore\n  {\n    public IEnumerable<Event> GetEvents(long firstEventSequenceNumber, long lastEventSequenceNumber)\n    {\n      if (firstEventSequenceNumber > 100)\n        return Enumerable.Empty<Event>();\n      else\n        return Enumerable\n          .Range((int) firstEventSequenceNumber, (int) (lastEventSequenceNumber - firstEventSequenceNumber))\n          .Select(i => new Event(i, DateTimeOffset.Now.AddMinutes(i), \"some event\", i));\n    }\n\n    public void Raise(string eventName, object content)\n    {\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramUnitTests/LoyaltyProgramUnitTests.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>df4d91a9-c2b2-47a1-b3f5-74d3a03e7aaf</ProjectGuid>\n    <RootNamespace>LoyaltyProgramUnitTests</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramUnitTests/TestModule_should.cs",
    "content": "namespace LoyaltyProgramUnitTests\n{\n  using System.Threading.Tasks;\n  using Nancy;\n  using Nancy.Testing;\n  using Xunit;\n\n  public class TestModule_should\n  {\n    public class TestModule : NancyModule\n    {\n      public TestModule()\n      {\n        Get(\"/\", _ => 200);\n      }\n    }\n\n    [Fact]\n    public async Task respond_ok_to_request_to_root()\n    {\n      var sut = new Browser(with => with.Module<TestModule>());\n      var actual = await sut.Get(\"/\");\n\n      Assert.Equal(HttpStatusCode.OK, actual.StatusCode);\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramUnitTests/UserModule_should.cs",
    "content": "namespace LoyaltyProgramUnitTests\n{\n  using System;\n  using System.Threading.Tasks;\n  using LoyaltyProgram;\n  using Nancy;\n  using Nancy.Testing;\n  using Xunit;\n\n  public class UserModule_should\n  {\n    private Browser sut;\n\n    public UserModule_should()\n    {\n      this.sut = new Browser(\n        new Bootstrapper(),\n        defaultsTo => defaultsTo.Accept(\"application/json\"));\n    }\n\n    [Fact]\n    public async Task respond_not_when_queried_for_unregistered_user()\n    {\n      var actual = await sut.Get(\"/users/1000\");\n      Assert.Equal(HttpStatusCode.NotFound, actual.StatusCode);\n    }\n\n    [Fact]\n    public async Task allow_to_register_new_user()\n    {\n      var expected = new LoyaltyProgramUser() {Name = \"Chr\"};\n      var registrationResponse = await sut.Post(\"/users\", with => with.JsonBody(expected));\n      var newUser = registrationResponse.Body.DeserializeJson<LoyaltyProgramUser>();\n\n      var actual = await sut.Get($\"/users/{newUser.Id}\");\n\n      Assert.Equal(HttpStatusCode.OK, actual.StatusCode);\n      Assert.Equal(expected.Name, actual.Body.DeserializeJson<LoyaltyProgramUser>().Name);\n    }\n\n    [Fact]\n    public async Task allow_modififying_users()\n    {\n      var expected = \"jane\";\n      var user = new LoyaltyProgramUser() {Name = \"Chr\"};\n      var registrationResponse = await sut.Post(\"/users\", with => with.JsonBody(user));\n      var newUser = registrationResponse.Body.DeserializeJson<LoyaltyProgramUser>();\n\n      newUser.Name = expected;\n      var actual = await sut.Put($\"/users/{newUser.Id}\", with => with.JsonBody(newUser));\n\n      Assert.Equal(expected, actual.Body.DeserializeJson<LoyaltyProgramUser>().Name);\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter07/LoyaltyProgramUnitTests/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n\n  \"buildOptions\": {\n    \"preserveCompilationContext\": true\n  },\n\n  \"dependencies\": {\n    \"dotnet-test-xunit\": \"2.2.0-preview2-build1029\",\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"xunit\": \"2.1.0\",\n    \"Nancy.Testing\": \"2.0.0-barneyrubble\",\n    \"LoyaltyProgram\": {\"target\": \"project\"}\n\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"testRunner\": \"xunit\",\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgramUnitTests\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/.vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \".NET Core Launch (console)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/ShoppingCart.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false\n        },\n        {\n            \"name\": \".NET Core Launch (web)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/ShoppingCart.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false,\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            }\n        },\n        {\n            \"name\": \".NET Core Attach\",\n            \"type\": \"coreclr\",\n            \"request\": \"attach\",\n            \"processName\": \"<example>\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/.vscode/tasks.json",
    "content": "{\n    \"version\": \"0.1.0\",\n    \"command\": \"dotnet\",\n    \"isShellCommand\": true,\n    \"args\": [],\n    \"tasks\": [\n        {\n            \"taskName\": \"build\",\n            \"args\": [],\n            \"isBuildCommand\": true,\n            \"problemMatcher\": \"$msCompile\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/Application_Packages/LibOwin.cs",
    "content": "﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.\n// Copyright (c) Damian Hickey. All rights reserved. See License.txt in the project root for license information.\n\n// https://github.com/damianh/LibOwin\n// Modifying this file may result in difficulties when upgrading the package.\n// All types are internal. Add a LIBOWIN_PUBLIC compilation symbol to make them public.\n\nnamespace LibOwin.Infrastructure\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Linq;\n\n    internal static partial class Constants\n    {\n        internal const string Https = \"HTTPS\";\n\n        internal const string HttpDateFormat = \"r\";\n\n        internal static partial class Headers\n        {\n            internal const string ContentType = \"Content-Type\";\n            internal const string CacheControl = \"Cache-Control\";\n            internal const string MediaType = \"Media-Type\";\n            internal const string Accept = \"Accept\";\n            internal const string Host = \"Host\";\n            internal const string ETag = \"ETag\";\n            internal const string Location = \"Location\";\n            internal const string ContentLength = \"Content-Length\";\n            internal const string SetCookie = \"Set-Cookie\";\n            internal const string Expires = \"Expires\";\n        }\n    }\n\n    internal struct HeaderSegment : IEquatable<HeaderSegment>\n    {\n        private readonly StringSegment _formatting;\n        private readonly StringSegment _data;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public HeaderSegment(StringSegment formatting, StringSegment data)\n        {\n            _formatting = formatting;\n            _data = data;\n        }\n\n        public StringSegment Formatting\n        {\n            get { return _formatting; }\n        }\n\n        public StringSegment Data\n        {\n            get { return _data; }\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegment other)\n        {\n            return _formatting.Equals(other._formatting) && _data.Equals(other._data);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegment && Equals((HeaderSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return (_formatting.GetHashCode() * 397) ^ _data.GetHashCode();\n            }\n        }\n\n        public static bool operator ==(HeaderSegment left, HeaderSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegment left, HeaderSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n    }\n\n    internal struct HeaderSegmentCollection : IEnumerable<HeaderSegment>, IEquatable<HeaderSegmentCollection>\n    {\n        private readonly string[] _headers;\n\n        public HeaderSegmentCollection(string[] headers)\n        {\n            _headers = headers;\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegmentCollection other)\n        {\n            return Equals(_headers, other._headers);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegmentCollection && Equals((HeaderSegmentCollection)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return (_headers != null ? _headers.GetHashCode() : 0);\n        }\n\n        public static bool operator ==(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public Enumerator GetEnumerator()\n        {\n            return new Enumerator(_headers);\n        }\n\n        IEnumerator<HeaderSegment> IEnumerable<HeaderSegment>.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        internal struct Enumerator : IEnumerator<HeaderSegment>\n        {\n            private readonly string[] _headers;\n            private int _index;\n\n            private string _header;\n            private int _headerLength;\n            private int _offset;\n\n            private int _leadingStart;\n            private int _leadingEnd;\n            private int _valueStart;\n            private int _valueEnd;\n            private int _trailingStart;\n\n            private Mode _mode;\n\n            private static readonly string[] NoHeaders = new string[0];\n\n            public Enumerator(string[] headers)\n            {\n                _headers = headers ?? NoHeaders;\n                _header = string.Empty;\n                _headerLength = -1;\n                _index = -1;\n                _offset = -1;\n                _leadingStart = -1;\n                _leadingEnd = -1;\n                _valueStart = -1;\n                _valueEnd = -1;\n                _trailingStart = -1;\n                _mode = Mode.Leading;\n            }\n\n            private enum Mode\n            {\n                Leading,\n                Value,\n                ValueQuoted,\n                Trailing,\n                Produce,\n            }\n\n            private enum Attr\n            {\n                Value,\n                Quote,\n                Delimiter,\n                Whitespace\n            }\n\n            public HeaderSegment Current\n            {\n                get\n                {\n                    return new HeaderSegment(\n                        new StringSegment(_header, _leadingStart, _leadingEnd - _leadingStart),\n                        new StringSegment(_header, _valueStart, _valueEnd - _valueStart));\n                }\n            }\n\n            object IEnumerator.Current\n            {\n                get { return Current; }\n            }\n\n            public void Dispose()\n            {\n            }\n\n            public bool MoveNext()\n            {\n                while (true)\n                {\n                    if (_mode == Mode.Produce)\n                    {\n                        _leadingStart = _trailingStart;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        if (_offset == _headerLength &&\n                            _leadingStart != -1 &&\n                            _leadingStart != _offset)\n                        {\n                            // Also produce trailing whitespace\n                            _leadingEnd = _offset;\n                            return true;\n                        }\n                        _mode = Mode.Leading;\n                    }\n\n                    // if end of a string\n                    if (_offset == _headerLength)\n                    {\n                        ++_index;\n                        _offset = -1;\n                        _leadingStart = 0;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        // if that was the last string\n                        if (_index == _headers.Length)\n                        {\n                            // no more move nexts\n                            return false;\n                        }\n\n                        // grab the next string\n                        _header = _headers[_index] ?? string.Empty;\n                        _headerLength = _header.Length;\n                    }\n                    while (true)\n                    {\n                        ++_offset;\n                        char ch = _offset == _headerLength ? (char)0 : _header[_offset];\n                        // todo - array of attrs\n                        Attr attr = char.IsWhiteSpace(ch) ? Attr.Whitespace : ch == '\\\"' ? Attr.Quote : (ch == ',' || ch == (char)0) ? Attr.Delimiter : Attr.Value;\n\n                        switch (_mode)\n                        {\n                            case Mode.Leading:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _leadingEnd = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Value:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Delimiter:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Value:\n                                        // more\n                                        break;\n                                    case Attr.Whitespace:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Trailing;\n                                        break;\n                                }\n                                break;\n                            case Mode.ValueQuoted:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Delimiter:\n                                        if (ch == (char)0)\n                                        {\n                                            _valueEnd = _offset;\n                                            _trailingStart = _offset;\n                                            _mode = Mode.Produce;\n                                        }\n                                        break;\n                                    case Attr.Value:\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Trailing:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                        }\n                        if (_mode == Mode.Produce)\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n\n            public void Reset()\n            {\n                _index = 0;\n                _offset = 0;\n                _leadingStart = 0;\n                _leadingEnd = 0;\n                _valueStart = 0;\n                _valueEnd = 0;\n            }\n        }\n    }\n\n    internal struct StringSegment : IEquatable<StringSegment>\n    {\n        private readonly string _buffer;\n        private readonly int _offset;\n        private readonly int _count;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public StringSegment(string buffer, int offset, int count)\n        {\n            _buffer = buffer;\n            _offset = offset;\n            _count = count;\n        }\n\n        public string Buffer\n        {\n            get { return _buffer; }\n        }\n\n        public int Offset\n        {\n            get { return _offset; }\n        }\n\n        public int Count\n        {\n            get { return _count; }\n        }\n\n        public string Value\n        {\n            get { return _offset == -1 ? null : _buffer.Substring(_offset, _count); }\n        }\n\n        public bool HasValue\n        {\n            get { return _offset != -1 && _count != 0 && _buffer != null; }\n        }\n\n        #region Equality members\n\n        public bool Equals(StringSegment other)\n        {\n            return string.Equals(_buffer, other._buffer) && _offset == other._offset && _count == other._count;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is StringSegment && Equals((StringSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hashCode = (_buffer != null ? _buffer.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ _offset;\n                hashCode = (hashCode * 397) ^ _count;\n                return hashCode;\n            }\n        }\n\n        public static bool operator ==(StringSegment left, StringSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(StringSegment left, StringSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public bool StartsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool EndsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset + _count - textLength, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool Equals(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count != textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public string Substring(int offset, int length)\n        {\n            return _buffer.Substring(_offset + offset, length);\n        }\n\n        public StringSegment Subsegment(int offset, int length)\n        {\n            return new StringSegment(_buffer, _offset + offset, length);\n        }\n\n        public override string ToString()\n        {\n            return Value ?? string.Empty;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AddCookieCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, string>)state;\n            if (!dictionary.ContainsKey(name))\n            {\n                dictionary.Add(name, value);\n            }\n        };\n\n        private static readonly char[] SemicolonAndComma = new[] { ';', ',' };\n\n        internal static IDictionary<string, string> GetCookies(IOwinRequest request)\n        {\n            var cookies = request.Get<IDictionary<string, string>>(\"Microsoft.Owin.Cookies#dictionary\");\n            if (cookies == null)\n            {\n                cookies = new Dictionary<string, string>(StringComparer.Ordinal);\n                request.Set(\"Microsoft.Owin.Cookies#dictionary\", cookies);\n            }\n\n            string text = GetHeader(request.Headers, \"Cookie\");\n            if (request.Get<string>(\"Microsoft.Owin.Cookies#text\") != text)\n            {\n                cookies.Clear();\n                ParseDelimited(text, SemicolonAndComma, AddCookieCallback, cookies);\n                request.Set(\"Microsoft.Owin.Cookies#text\", text);\n            }\n            return cookies;\n        }\n\n        internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)\n        {\n            int textLength = text.Length;\n            int equalIndex = text.IndexOf('=');\n            if (equalIndex == -1)\n            {\n                equalIndex = textLength;\n            }\n            int scanIndex = 0;\n            while (scanIndex < textLength)\n            {\n                int delimiterIndex = text.IndexOfAny(delimiters, scanIndex);\n                if (delimiterIndex == -1)\n                {\n                    delimiterIndex = textLength;\n                }\n                if (equalIndex < delimiterIndex)\n                {\n                    while (scanIndex != equalIndex && char.IsWhiteSpace(text[scanIndex]))\n                    {\n                        ++scanIndex;\n                    }\n                    string name = text.Substring(scanIndex, equalIndex - scanIndex);\n                    string value = text.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);\n                    callback(\n                        Uri.UnescapeDataString(name.Replace('+', ' ')),\n                        Uri.UnescapeDataString(value.Replace('+', ' ')),\n                        state);\n                    equalIndex = text.IndexOf('=', delimiterIndex);\n                    if (equalIndex == -1)\n                    {\n                        equalIndex = textLength;\n                    }\n                }\n                scanIndex = delimiterIndex + 1;\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        public static string GetHeader(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        public static IEnumerable<string> GetHeaderSplit(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : GetHeaderSplitImplementation(values);\n        }\n\n        private static IEnumerable<string> GetHeaderSplitImplementation(string[] values)\n        {\n            foreach (var segment in new HeaderSegmentCollection(values))\n            {\n                if (segment.Data.HasValue)\n                {\n                    yield return DeQuote(segment.Data.Value);\n                }\n            }\n        }\n\n        public static string[] GetHeaderUnmodified(IDictionary<string, string[]> headers, string key)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            string[] values;\n            return headers.TryGetValue(key, out values) ? values : null;\n        }\n\n        public static void SetHeader(IDictionary<string, string[]> headers, string key, string value)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { value };\n            }\n        }\n\n        public static void SetHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        // Quote items that contain comas and are not already quoted.\n        private static string QuoteIfNeeded(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Contains(','))\n            {\n                if (value[0] != '\"' || value[value.Length - 1] != '\"')\n                {\n                    value = '\"' + value + '\"';\n                }\n            }\n\n            return value;\n        }\n\n        private static string DeQuote(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Length > 1 && value[0] == '\"' && value[value.Length - 1] == '\"')\n            {\n                value = value.Substring(1, value.Length - 2);\n            }\n\n            return value;\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = values;\n            }\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, IEnumerable<string> values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            headers[key] = values.ToArray();\n        }\n\n        public static void AppendHeader(IDictionary<string, string[]> headers, string key, string values)\n        {\n            if (string.IsNullOrWhiteSpace(values))\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeader(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + values };\n            }\n        }\n\n        public static void AppendHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeaderJoined(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        public static void AppendHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string[] existing = GetHeaderUnmodified(headers, key);\n            if (existing == null)\n            {\n                SetHeaderUnmodified(headers, key, values);\n            }\n            else\n            {\n                SetHeaderUnmodified(headers, key, existing.Concat(values));\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AppendItemCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, List<String>>)state;\n\n            List<string> existing;\n            if (!dictionary.TryGetValue(name, out existing))\n            {\n                dictionary.Add(name, new List<string>(1) { value });\n            }\n            else\n            {\n                existing.Add(value);\n            }\n        };\n\n        private static readonly char[] AmpersandAndSemicolon = new[] { '&', ';' };\n\n        internal static IDictionary<string, string[]> GetQuery(IOwinRequest request)\n        {\n            var query = request.Get<IDictionary<string, string[]>>(\"Microsoft.Owin.Query#dictionary\");\n            if (query == null)\n            {\n                query = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n                request.Set(\"Microsoft.Owin.Query#dictionary\", query);\n            }\n\n            string text = request.QueryString.Value;\n            if (request.Get<string>(\"Microsoft.Owin.Query#text\") != text)\n            {\n                query.Clear();\n                var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n                ParseDelimited(text, AmpersandAndSemicolon, AppendItemCallback, accumulator);\n                foreach (var kv in accumulator)\n                {\n                    query.Add(kv.Key, kv.Value.ToArray());\n                }\n                request.Set(\"Microsoft.Owin.Query#text\", text);\n            }\n            return query;\n        }\n\n        internal static IFormCollection GetForm(string text)\n        {\n            IDictionary<string, string[]> form = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n            ParseDelimited(text, new[] { '&' }, AppendItemCallback, accumulator);\n            foreach (var kv in accumulator)\n            {\n                form.Add(kv.Key, kv.Value.ToArray());\n            }\n            return new FormCollection(form);\n        }\n\n        internal static string GetJoinedValue(IDictionary<string, string[]> store, string key)\n        {\n            string[] values = GetUnmodifiedValues(store, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        internal static string[] GetUnmodifiedValues(IDictionary<string, string[]> store, string key)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n            string[] values;\n            return store.TryGetValue(key, out values) ? values : null;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        internal static string GetHost(IOwinRequest request)\n        {\n            IHeaderDictionary headers = request.Headers;\n\n            string host = GetHeader(headers, \"Host\");\n            if (!string.IsNullOrWhiteSpace(host))\n            {\n                return host;\n            }\n\n            string localIpAddress = request.LocalIpAddress ?? \"localhost\";\n            var localPort = request.Get<string>(OwinConstants.CommonKeys.LocalPort);\n            return string.IsNullOrWhiteSpace(localPort) ? localIpAddress : (localIpAddress + \":\" + localPort);\n        }\n    }\n}\n\nnamespace LibOwin\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Globalization;\n    using System.IO;\n    using System.Linq;\n    using System.Security.Claims;\n    using System.Security.Principal;\n    using System.Text;\n    using System.Threading;\n    using System.Threading.Tasks;\n    using LibOwin.Infrastructure;\n\n    #if LIBOWIN_PUBLIC\n\n    public partial class CookieOptions { }\n    public partial class FormCollection { }\n    public partial class HeaderDictionary { }\n    public partial struct HostString { }\n    public partial interface IFormCollection { }\n    public partial interface IHeaderDictionary { }\n    public partial interface IOwinContext { }\n    public partial interface IOwinRequest { }\n    public partial interface IOwinResponse { }\n    public partial interface IReadableStringCollection { }\n    public partial class OwinContext { }\n    public partial class OwinRequest { }\n    public partial class OwinResponse { }\n    public partial struct PathString { }\n    public partial struct QueryString { }\n    public partial class ReadableStringCollection { }\n    public partial class RequestCookieCollection { }\n    public partial class ResponseCookieCollection { }\n    public partial class IOwinResponseExtension { }\n\n    #endif\n\n    /// <summary>\n    /// Options used to create a new cookie.\n    /// </summary>\n    partial class CookieOptions\n    {\n        /// <summary>\n        /// Creates a default cookie with a path of '/'.\n        /// </summary>\n        public CookieOptions()\n        {\n            Path = \"/\";\n        }\n\n        /// <summary>\n        /// Gets or sets the domain to associate the cookie with.\n        /// </summary>\n        /// <returns>The domain to associate the cookie with.</returns>\n        public string Domain { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cookie path.\n        /// </summary>\n        /// <returns>The cookie path.</returns>\n        public string Path { get; set; }\n\n        /// <summary>\n        /// Gets or sets the expiration date and time for the cookie.\n        /// </summary>\n        /// <returns>The expiration date and time for the cookie.</returns>\n        public DateTime? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether to transmit the cookie using Secure Sockets Layer (SSL)—that is, over HTTPS only.\n        /// </summary>\n        /// <returns>true to transmit the cookie only over an SSL connection (HTTPS); otherwise, false.</returns>\n        public bool Secure { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether a cookie is accessible by client-side script.\n        /// </summary>\n        /// <returns>true if a cookie is accessible by client-side script; otherwise, false.</returns>\n        public bool HttpOnly { get; set; }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial class FormCollection : ReadableStringCollection, IFormCollection\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.FormCollection\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The store for the form.</param>\n        public FormCollection(IDictionary<string, string[]> store)\n            : base(store)\n        {}\n    }\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial class HeaderDictionary : IHeaderDictionary\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The underlying data store.</param>\n        public HeaderDictionary(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Gets an <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public ICollection<string> Keys\n        {\n            get { return Store.Keys; }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        public ICollection<string[]> Values\n        {\n            get { return Store.Values; }\n        }\n\n        /// <summary>\n        /// Gets the number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>The number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public int Count\n        {\n            get { return Store.Count; }\n        }\n\n        /// <summary>\n        /// Gets a value that indicates whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode.\n        /// </summary>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode; otherwise, false.</returns>\n        public bool IsReadOnly\n        {\n            get { return Store.IsReadOnly; }\n        }\n\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n            set { Set(key, value); }\n        }\n\n        /// <summary>\n        /// Throws KeyNotFoundException if the key is not present.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns></returns>\n        string[] IDictionary<string, string[]>.this[string key]\n        {\n            get { return Store[key]; }\n            set { Store[key] = value; }\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetHeader(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection without modification, or null if the key is not present.</returns>\n        public IList<string> GetValues(string key)\n        {\n            return OwinHelpers.GetHeaderUnmodified(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        public IList<string> GetCommaSeparatedValues(string key)\n        {\n            IEnumerable<string> values = OwinHelpers.GetHeaderSplit(Store, key);\n            return values == null ? null : values.ToList();\n        }\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Append(string key, string value)\n        {\n            OwinHelpers.AppendHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Set(string key, string value)\n        {\n            OwinHelpers.SetHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Adds the given header and values to the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header values.</param>\n        public void Add(string key, string[] value)\n        {\n            Store.Add(key, value);\n        }\n\n        /// <summary>\n        /// Determines whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key.\n        /// </summary>\n        /// <param name=\"key\">The key.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key; otherwise, false.</returns>\n        public bool ContainsKey(string key)\n        {\n            return Store.ContainsKey(key);\n        }\n\n        /// <summary>\n        /// Removes the given header from the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(string key)\n        {\n            return Store.Remove(key);\n        }\n\n        /// <summary>\n        /// Retrieves a value from the dictionary.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The value.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains the key; otherwise, false.</returns>\n        public bool TryGetValue(string key, out string[] value)\n        {\n            return Store.TryGetValue(key, out value);\n        }\n\n        /// <summary>\n        /// Adds a new list of items to the collection.\n        /// </summary>\n        /// <param name=\"item\">The item to add.</param>\n        public void Add(KeyValuePair<string, string[]> item)\n        {\n            Store.Add(item);\n        }\n\n        /// <summary>\n        /// Clears the entire list of objects.\n        /// </summary>\n        public void Clear()\n        {\n            Store.Clear();\n        }\n\n        /// <summary>\n        /// Returns a value indicating whether the specified object occurs within this collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object occurs within this collection; otherwise, false.</returns>\n        public bool Contains(KeyValuePair<string, string[]> item)\n        {\n            return Store.Contains(item);\n        }\n\n        /// <summary>\n        /// Copies the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> elements to a one-dimensional Array instance at the specified index.\n        /// </summary>\n        /// <param name=\"array\">The one-dimensional Array that is the destination of the specified objects copied from the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</param>\n        /// <param name=\"arrayIndex\">The zero-based index in <paramref name=\"array\" /> at which copying begins.</param>\n        public void CopyTo(KeyValuePair<string, string[]>[] array, int arrayIndex)\n        {\n            Store.CopyTo(array, arrayIndex);\n        }\n\n        /// <summary>\n        /// Removes the given item from the the collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(KeyValuePair<string, string[]> item)\n        {\n            return Store.Remove(item);\n        }\n    }\n\n    /// <summary>\n    /// Represents the host portion of a Uri can be used to construct Uri's properly formatted and encoded for use in\n    /// HTTP headers.\n    /// </summary>\n    partial struct HostString : IEquatable<HostString>\n    {\n        private readonly string _value;\n\n        /// <summary>\n        /// Creates a new HostString without modification. The value should be Unicode rather than punycode, and may have a port.\n        /// IPv4 and IPv6 addresses are also allowed, and also may have ports.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        public HostString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Returns the original value from the constructor.\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// Returns the value as normalized by ToUriComponent().\n        /// </summary>\n        /// <returns></returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Returns the value properly formatted and encoded for use in a URI in a HTTP header.\n        /// Any Unicode is converted to punycode. IPv6 addresses will have brackets added if they are missing.\n        /// </summary>\n        /// <returns></returns>\n        public string ToUriComponent()\n        {\n            int index;\n            if (string.IsNullOrEmpty(_value))\n            {\n                return string.Empty;\n            }\n            else if (_value.IndexOf('[') >= 0)\n            {\n                // IPv6 in brackets [::1], maybe with port\n                return _value;\n            }\n            else if ((index = _value.IndexOf(':')) >= 0\n                && index < _value.Length - 1\n                && _value.IndexOf(':', index + 1) >= 0)\n            {\n                // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                return \"[\" + _value + \"]\";\n            }\n            else if (index >= 0)\n            {\n                // Has a port\n                string port = _value.Substring(index);\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value, 0, index) + port;\n            }\n            else\n            {\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value);\n            }\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the given uri component.\n        /// Any punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uriComponent\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(string uriComponent)\n        {\n            if (!string.IsNullOrEmpty(uriComponent))\n            {\n                int index;\n                if (uriComponent.IndexOf('[') >= 0)\n                {\n                    // IPv6 in brackets [::1], maybe with port\n                }\n                else if ((index = uriComponent.IndexOf(':')) >= 0\n                    && index < uriComponent.Length - 1\n                    && uriComponent.IndexOf(':', index + 1) >= 0)\n                {\n                    // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                }\n                else if (uriComponent.IndexOf(\"xn--\", StringComparison.Ordinal) >= 0)\n                {\n                    // Contains punycode\n                    if (index >= 0)\n                    {\n                        // Has a port\n                        string port = uriComponent.Substring(index);\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent, 0, index) + port;\n                    }\n                    else\n                    {\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent);\n                    }\n                }\n            }\n            return new HostString(uriComponent);\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the host and port of the give Uri instance.\n        /// Punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uri\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new HostString(uri.GetComponents(\n                UriComponents.NormalizedHost | // Always convert punycode to Unicode.\n                UriComponents.HostAndPort, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Compares the equality of the Value property, ignoring case.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(HostString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares against the given object only if it is a HostString.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is HostString && Equals((HostString)obj);\n        }\n\n        /// <summary>\n        /// Gets a hash code for the value.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(HostString left, HostString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(HostString left, HostString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial interface IFormCollection : IReadableStringCollection\n    {}\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, string[]>\n    {\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        new string this[string key] { get; set; }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        IList<string> GetCommaSeparatedValues(string key);\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Append(string key, string value);\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendCommaSeparatedValues(string key, params string[] values);\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Set(string key, string value);\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetCommaSeparatedValues(string key, params string[] values);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinContext\n    {\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        IOwinRequest Request { get; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        IOwinResponse Response { get; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        TextWriter TraceOutput { get; set; }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinContext Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinRequest\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        string Method { get; set; }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        string Scheme { get; set; }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        bool IsSecure { get; }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        HostString Host { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        PathString PathBase { get; set; }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        PathString Path { get; set; }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        QueryString QueryString { get; set; }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        IReadableStringCollection Query { get; }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        Uri Uri { get; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        RequestCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        string CacheControl { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        string MediaType { get; set; }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        string Accept { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        CancellationToken CallCancelled { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        string LocalIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        int? LocalPort { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        string RemoteIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        int? RemotePort { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        ClaimsPrincipal User { get; set; }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        Task<IFormCollection> ReadFormAsync();\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinRequest Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinResponse\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        int StatusCode { get; set; }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        string ReasonPhrase { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        ResponseCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        long? ContentLength { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        DateTimeOffset? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        string ETag { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        void OnSendingHeaders(Action<object> callback, object state);\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        void Redirect(string location);\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        void Write(string text);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        void Write(byte[] data);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        void Write(byte[] data, int offset, int count);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, int offset, int count, CancellationToken token);\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinResponse Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// Accessors for headers, query, forms, etc.\n    /// </summary>\n    partial interface IReadableStringCollection : IEnumerable<KeyValuePair<string, string[]>>\n    {\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string this[string key] { get; }\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string Get(string key);\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        IList<string> GetValues(string key);\n\n        // Raw\n    }\n\n    internal static class OwinConstants\n    {\n        #region OWIN v1.0.0 - 3.2.1. Request Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string RequestScheme = \"owin.RequestScheme\";\n        public const string RequestMethod = \"owin.RequestMethod\";\n        public const string RequestPathBase = \"owin.RequestPathBase\";\n        public const string RequestPath = \"owin.RequestPath\";\n        public const string RequestQueryString = \"owin.RequestQueryString\";\n        public const string RequestProtocol = \"owin.RequestProtocol\";\n        public const string RequestHeaders = \"owin.RequestHeaders\";\n        public const string RequestBody = \"owin.RequestBody\";\n        public const string RequestUser = \"owin.RequestUser\"; //owin 1.0.1\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.2. Response Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string ResponseStatusCode = \"owin.ResponseStatusCode\";\n        public const string ResponseReasonPhrase = \"owin.ResponseReasonPhrase\";\n        public const string ResponseProtocol = \"owin.ResponseProtocol\";\n        public const string ResponseHeaders = \"owin.ResponseHeaders\";\n        public const string ResponseBody = \"owin.ResponseBody\";\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.3. Other Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string CallCancelled = \"owin.CallCancelled\";\n\n        public const string OwinVersion = \"owin.Version\";\n\n        #endregion\n\n        #region OWIN Keys for IAppBuilder.Properties\n\n        internal static class Builder\n        {\n            public const string AddSignatureConversion = \"builder.AddSignatureConversion\";\n            public const string DefaultApp = \"builder.DefaultApp\";\n        }\n\n        #endregion\n\n        #region OWIN Key Guidelines and Common Keys - 6. Common keys\n\n        // http://owin.org/spec/CommonKeys.html\n\n        internal static class CommonKeys\n        {\n            public const string ClientCertificate = \"ssl.ClientCertificate\";\n            public const string RemoteIpAddress = \"server.RemoteIpAddress\";\n            public const string RemotePort = \"server.RemotePort\";\n            public const string LocalIpAddress = \"server.LocalIpAddress\";\n            public const string LocalPort = \"server.LocalPort\";\n            public const string IsLocal = \"server.IsLocal\";\n            public const string TraceOutput = \"host.TraceOutput\";\n            public const string Addresses = \"host.Addresses\";\n            public const string AppName = \"host.AppName\";\n            public const string Capabilities = \"server.Capabilities\";\n            public const string OnSendingHeaders = \"server.OnSendingHeaders\";\n            public const string OnAppDisposing = \"host.OnAppDisposing\";\n            public const string Scheme = \"scheme\";\n            public const string Host = \"host\";\n            public const string Port = \"port\";\n            public const string Path = \"path\";\n        }\n\n        #endregion\n\n        #region SendFiles v0.3.0\n\n        // http://owin.org/extensions/owin-SendFile-Extension-v0.3.0.htm\n\n        internal static class SendFiles\n        {\n            // 3.1. Startup\n\n            public const string Version = \"sendfile.Version\";\n            public const string Support = \"sendfile.Support\";\n            public const string Concurrency = \"sendfile.Concurrency\";\n\n            // 3.2. Per Request\n\n            public const string SendAsync = \"sendfile.SendAsync\";\n        }\n\n        #endregion\n\n        #region Opaque v0.3.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class OpaqueConstants\n        {\n            // 3.1. Startup\n            public const string Version = \"opaque.Version\";\n\n            // 3.2. Per Request\n            public const string Upgrade = \"opaque.Upgrade\";\n\n            // 5. Consumption\n            public const string Stream = \"opaque.Stream\";\n            // public const string Version = \"opaque.Version\"; // redundant, declared above\n            public const string CallCancelled = \"opaque.CallCancelled\";\n        }\n\n        #endregion\n\n        #region WebSocket v0.4.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class WebSocket\n        {\n            // 3.1. Startup\n            public const string Version = \"websocket.Version\";\n\n            // 3.2. Per Request\n            public const string Accept = \"websocket.Accept\";\n\n            // 4. Accept\n            public const string SubProtocol = \"websocket.SubProtocol\";\n\n            // 5. Consumption\n            public const string SendAsync = \"websocket.SendAsync\";\n            public const string ReceiveAsync = \"websocket.ReceiveAsync\";\n            public const string CloseAsync = \"websocket.CloseAsync\";\n            // public const string Version = \"websocket.Version\"; // redundant, declared above\n            public const string CallCancelled = \"websocket.CallCancelled\";\n            public const string ClientCloseStatus = \"websocket.ClientCloseStatus\";\n            public const string ClientCloseDescription = \"websocket.ClientCloseDescription\";\n        }\n\n        #endregion\n\n        #region Security v0.1.0\n\n        // http://owin.org/extensions/owin-Security-Extension-v0.1.0.htm\n\n        internal static class Security\n        {\n            // 3.2. Per Request\n\n            public const string User = \"server.User\";\n\n            public const string Authenticate = \"security.Authenticate\";\n\n            // 3.3. Response\n\n            public const string SignIn = \"security.SignIn\";\n\n            public const string SignOut = \"security.SignOut\";\n\n            public const string SignOutProperties = \"security.SignOutProperties\";\n\n            public const string Challenge = \"security.Challenge\";\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinContext : IOwinContext\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinContext()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Create a new wrapper.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinContext(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        public virtual IOwinRequest Request { get; private set; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        public virtual IOwinResponse Response { get; private set; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        public virtual TextWriter TraceOutput\n        {\n            get { return Get<TextWriter>(OwinConstants.CommonKeys.TraceOutput); }\n            set { Set<TextWriter>(OwinConstants.CommonKeys.TraceOutput, value); }\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinContext Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinRequest : IOwinRequest\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinRequest()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Create a new environment wrapper exposing request properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinRequest(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        public virtual string Method\n        {\n            get { return Get<string>(OwinConstants.RequestMethod); }\n            set { Set(OwinConstants.RequestMethod, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        public virtual string Scheme\n        {\n            get { return Get<string>(OwinConstants.RequestScheme); }\n            set { Set(OwinConstants.RequestScheme, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        public virtual bool IsSecure\n        {\n            get { return string.Equals(Scheme, Constants.Https, StringComparison.OrdinalIgnoreCase); }\n        }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        public virtual HostString Host\n        {\n            get { return new HostString(OwinHelpers.GetHost(this)); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Host, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        public virtual PathString PathBase\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPathBase)); }\n            set { Set(OwinConstants.RequestPathBase, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        public virtual PathString Path\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPath)); }\n            set { Set(OwinConstants.RequestPath, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        public virtual QueryString QueryString\n        {\n            get { return new QueryString(Get<string>(OwinConstants.RequestQueryString)); }\n            set { Set(OwinConstants.RequestQueryString, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        public virtual IReadableStringCollection Query\n        {\n            get { return new ReadableStringCollection(OwinHelpers.GetQuery(this)); }\n        }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        public virtual Uri Uri\n        {\n            get { return new Uri(Scheme + \"//\" + Host + PathBase + Path + QueryString); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.RequestProtocol); }\n            set { Set(OwinConstants.RequestProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.RequestHeaders); }\n        }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        public RequestCookieCollection Cookies\n        {\n            get { return new RequestCookieCollection(OwinHelpers.GetCookies(this)); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        public virtual string CacheControl\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.CacheControl); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.CacheControl, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        public virtual string MediaType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.MediaType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.MediaType, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        public virtual string Accept\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Accept); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Accept, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.RequestBody); }\n            set { Set(OwinConstants.RequestBody, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        public virtual CancellationToken CallCancelled\n        {\n            get { return Get<CancellationToken>(OwinConstants.CallCancelled); }\n            set { Set(OwinConstants.CallCancelled, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        public virtual string LocalIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalIpAddress); }\n            set { Set(OwinConstants.CommonKeys.LocalIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        public virtual int? LocalPort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(LocalPortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    LocalPortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.LocalPort);\n                }\n            }\n        }\n\n        private string LocalPortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalPort); }\n            set { Set(OwinConstants.CommonKeys.LocalPort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        public virtual string RemoteIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemoteIpAddress); }\n            set { Set(OwinConstants.CommonKeys.RemoteIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        public virtual int? RemotePort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(RemotePortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    RemotePortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.RemotePort);\n                }\n            }\n        }\n\n        private string RemotePortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemotePort); }\n            set { Set(OwinConstants.CommonKeys.RemotePort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        public virtual ClaimsPrincipal User\n        {\n            get\n            {\n                var claimsPrincipal = Get<ClaimsPrincipal>(OwinConstants.RequestUser);\n                return claimsPrincipal ?? Get<IPrincipal>(OwinConstants.Security.User) as ClaimsPrincipal;\n            }\n            set { Set(OwinConstants.RequestUser, value); }\n        }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        public async Task<IFormCollection> ReadFormAsync()\n        {\n            var form = Get<IFormCollection>(\"Microsoft.Owin.Form#collection\");\n            if (form == null)\n            {\n                string text;\n                // Don't close, it prevents re-winding.\n                using (var reader = new StreamReader(Body, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4 * 1024, leaveOpen: true))\n                {\n                    text = await reader.ReadToEndAsync();\n                }\n                form = OwinHelpers.GetForm(text);\n                Set(\"Microsoft.Owin.Form#collection\", form);\n            }\n\n            return form;\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinRequest Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinResponse : IOwinResponse\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinResponse()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Creates a new environment wrapper exposing response properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinResponse(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        public virtual int StatusCode\n        {\n            get { return Get<int>(OwinConstants.ResponseStatusCode, 200); }\n            set { Set(OwinConstants.ResponseStatusCode, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        public virtual string ReasonPhrase\n        {\n            get { return Get<string>(OwinConstants.ResponseReasonPhrase); }\n            set { Set(OwinConstants.ResponseReasonPhrase, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.ResponseProtocol); }\n            set { Set(OwinConstants.ResponseProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders); }\n        }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        public virtual ResponseCookieCollection Cookies\n        {\n            get { return new ResponseCookieCollection(Headers); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        public virtual long? ContentLength\n        {\n            get\n            {\n                long value;\n                if (long.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentLength), out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentLength,\n                        value.Value.ToString(CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.ContentLength);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        public virtual DateTimeOffset? Expires\n        {\n            get\n            {\n                DateTimeOffset value;\n                if (DateTimeOffset.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Expires),\n                    CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Expires,\n                        value.Value.ToString(Constants.HttpDateFormat, CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.Expires);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        public virtual string ETag\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ETag); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ETag, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.ResponseBody); }\n            set { Set(OwinConstants.ResponseBody, value); }\n        }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public virtual void OnSendingHeaders(Action<object> callback, object state)\n        {\n            var onSendingHeaders = Get<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);\n            if (onSendingHeaders == null)\n            {\n                throw new NotSupportedException(Resources.Exception_MissingOnSendingHeaders);\n            }\n            onSendingHeaders(callback, state);\n        }\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        public virtual void Redirect(string location)\n        {\n            StatusCode = 302;\n            OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Location, location);\n        }\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        public virtual void Write(string text)\n        {\n            Write(Encoding.UTF8.GetBytes(text));\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        public virtual void Write(byte[] data)\n        {\n            Write(data, 0, data == null ? 0 : data.Length);\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        public virtual void Write(byte[] data, int offset, int count)\n        {\n            Body.Write(data, offset, count);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text)\n        {\n            return WriteAsync(text, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text, CancellationToken token)\n        {\n            return WriteAsync(Encoding.UTF8.GetBytes(text), token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data)\n        {\n            return WriteAsync(data, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, CancellationToken token)\n        {\n            return WriteAsync(data, 0, data == null ? 0 : data.Length, token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, int offset, int count, CancellationToken token)\n        {\n            return Body.WriteAsync(data, offset, count, token);\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            return Get(key, default(T));\n        }\n\n        private T Get<T>(string key, T fallback)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : fallback;\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinResponse Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct PathString : IEquatable<PathString>\n    {\n        private static readonly Func<string, string> EscapeDataString = Uri.EscapeDataString;\n\n        /// <summary>\n        /// Represents the empty path. This field is read-only.\n        /// </summary>\n        public static readonly PathString Empty = new PathString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initialize the path string with a given value. This value must be in un-escaped format. Use\n        /// PathString.FromUriComponent(value) if you have a path value which is in an escaped format.\n        /// </summary>\n        /// <param name=\"value\">The unescaped path to be assigned to the Value property.</param>\n        public PathString(string value)\n        {\n            if (!String.IsNullOrEmpty(value) && value[0] != '/')\n            {\n                throw new ArgumentException(Resources.Exception_PathMustStartWithSlash, \"value\");\n            }\n            _value = value;\n        }\n\n        /// <summary>\n        /// The unescaped path value\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the path is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrEmpty(_value); }\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public string ToUriComponent()\n        {\n            if (HasValue)\n            {\n                if (RequiresEscaping(_value))\n                {\n                    // TODO: Measure the cost of this escaping and consider optimizing.\n                    return String.Join(\"/\", _value.Split('/').Select(EscapeDataString));\n                }\n                return _value;\n            }\n            return String.Empty;\n        }\n\n        // Very conservative, these characters do not need to be escaped in a path.\n        private static bool RequiresEscaping(string value)\n        {\n            for (int i = 0; i < value.Length; i++)\n            {\n                char c = value[i];\n                // Check conservatively for safe characters. See http://www.ietf.org/rfc/rfc3986.txt\n                bool safeChar =\n                    (('a' <= c && c <= 'z')\n                    || ('A' <= c && c <= 'Z')\n                    || ('0' <= c && c <= '9')\n                    || c == '/' || c == '-' || c == '_');\n                if (!safeChar)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a path.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped path as it appears in the URI format.</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(string uriComponent)\n        {\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(Uri.UnescapeDataString(uriComponent));\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(\"/\" + uri.GetComponents(UriComponents.Path, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                return value1.Length == value2.Length || value1[value2.Length] == '/';\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <param name=\"remaining\">Any remaining segments from this instance not included in the other instance.</param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other, out PathString remaining)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                if (value1.Length == value2.Length || value1[value2.Length] == '/')\n                {\n                    remaining = new PathString(value1.Substring(value2.Length));\n                    return true;\n                }\n            }\n            remaining = Empty;\n            return false;\n        }\n\n        /// <summary>\n        /// Adds two PathString instances into a combined PathString value.\n        /// </summary>\n        /// <returns>The combined PathString value</returns>\n        public PathString Add(PathString other)\n        {\n            return new PathString(Value + other.Value);\n        }\n\n        /// <summary>\n        /// Combines a PathString and QueryString into the joined URI formatted string value.\n        /// </summary>\n        /// <returns>The joined URI formatted string value</returns>\n        public string Add(QueryString other)\n        {\n            return ToUriComponent() + other.ToUriComponent();\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value using a specific StringComparison type\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison</param>\n        /// <param name=\"comparisonType\">The StringComparison type to use</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other, StringComparison comparisonType)\n        {\n            return string.Equals(_value, other._value, comparisonType);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"obj\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is PathString && Equals((PathString)obj, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation.\n        /// </summary>\n        /// <returns>The hash code</returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public static bool operator ==(PathString left, PathString right)\n        {\n            return left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are not equal</returns>\n        public static bool operator !=(PathString left, PathString right)\n        {\n            return !left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static PathString operator +(PathString left, PathString right)\n        {\n            return left.Add(right);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static string operator +(PathString left, QueryString right)\n        {\n            return left.Add(right);\n        }\n    }\n\n    /// <summary>\n    /// Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct QueryString : IEquatable<QueryString>\n    {\n        /// <summary>\n        /// Represents the empty query string. This field is read-only.\n        /// </summary>\n        public static readonly QueryString Empty = new QueryString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initalize the query string with a given value. This value must be in escaped and delimited format without\n        /// a leading '?' character.\n        /// </summary>\n        /// <param name=\"value\">The query string to be assigned to the Value property.</param>\n        public QueryString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Initialize a query string with a single given parameter name and value. The value is\n        /// </summary>\n        /// <param name=\"name\">The unencoded parameter name</param>\n        /// <param name=\"value\">The unencoded parameter value</param>\n        public QueryString(string name, string value)\n        {\n            _value = Uri.EscapeDataString(name) + '=' + Uri.EscapeDataString(value);\n        }\n\n        /// <summary>\n        /// The unescaped query string without the leading '?' character\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the query string is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrWhiteSpace(_value); }\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentally\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public string ToUriComponent()\n        {\n            // Escape things properly so System.Uri doesn't mis-interpret the data.\n            return HasValue ? \"?\" + _value.Replace(\"#\", \"%23\") : String.Empty;\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a query.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped query as it appears in the URI format.</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(string uriComponent)\n        {\n            if (String.IsNullOrEmpty(uriComponent))\n            {\n                return new QueryString(string.Empty);\n            }\n            if (uriComponent[0] != '?')\n            {\n                throw new ArgumentException(Resources.Exception_QueryStringMustStartWithDelimiter, \"uriComponent\");\n            }\n            return new QueryString(uriComponent.Substring(1));\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new QueryString(uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped));\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(QueryString other)\n        {\n            return string.Equals(_value, other._value);\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is QueryString && Equals((QueryString)obj);\n        }\n\n        /// <summary>\n        /// Returns the hash code for this instance.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? _value.GetHashCode() : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(QueryString left, QueryString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(QueryString left, QueryString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Accessors for query, forms, etc.\n    /// </summary>\n    partial class ReadableStringCollection : IReadableStringCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public ReadableStringCollection(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetJoinedValue(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public IList<string> GetValues(string key)\n        {\n            string[] values;\n            Store.TryGetValue(key, out values);\n            return values;\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    /// <summary>\n    /// A wrapper for the request Cookie header\n    /// </summary>\n    partial class RequestCookieCollection : IEnumerable<KeyValuePair<string, string>>\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public RequestCookieCollection(IDictionary<string, string> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string> Store { get; set; }\n\n        /// <summary>\n        /// Returns null rather than throwing KeyNotFoundException\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get\n            {\n                string value;\n                Store.TryGetValue(key, out value);\n                return value;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    internal static class Resources\n    {\n        internal const string Exception_MissingOnSendingHeaders = \"The OWIN key 'server.OnSsoendingHeaders' is not available for this request.\";\n        internal const string Exception_PathMustStartWithSlash = \"The path must start with a '/' followed by one or more characters.\";\n        internal const string Exception_QueryStringMustStartWithDelimiter = \"The query string must start with a '?' unless null or empty.\";\n    }\n\n    /// <summary>\n    /// A wrapper for the response Set-Cookie header\n    /// </summary>\n    partial class ResponseCookieCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"headers\"></param>\n        public ResponseCookieCollection(IHeaderDictionary headers)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n\n            Headers = headers;\n        }\n\n        private IHeaderDictionary Headers { get; set; }\n\n        /// <summary>\n        /// Add a new cookie and value\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        public void Append(string key, string value)\n        {\n            Headers.AppendValues(Constants.Headers.SetCookie, Uri.EscapeDataString(key) + \"=\" + Uri.EscapeDataString(value) + \"; path=/\");\n        }\n\n        /// <summary>\n        /// Add a new cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        /// <param name=\"options\"></param>\n        public void Append(string key, string value, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n            bool expiresHasValue = options.Expires.HasValue;\n\n            string setCookieValue = string.Concat(\n                Uri.EscapeDataString(key),\n                \"=\",\n                Uri.EscapeDataString(value ?? string.Empty),\n                !domainHasValue ? null : \"; domain=\",\n                !domainHasValue ? null : options.Domain,\n                !pathHasValue ? null : \"; path=\",\n                !pathHasValue ? null : options.Path,\n                !expiresHasValue ? null : \"; expires=\",\n                !expiresHasValue ? null : options.Expires.Value.ToString(\"ddd, dd-MMM-yyyy HH:mm:ss \", CultureInfo.InvariantCulture) + \"GMT\",\n                !options.Secure ? null : \"; secure\",\n                !options.HttpOnly ? null : \"; HttpOnly\");\n            Headers.AppendValues(\"Set-Cookie\", setCookieValue);\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        public void Delete(string key)\n        {\n            Func<string, bool> predicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n\n            var deleteCookies = new[] { Uri.EscapeDataString(key) + \"=; expires=Thu, 01-Jan-1970 00:00:00 GMT\" };\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues == null || existingValues.Count == 0)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, deleteCookies);\n            }\n            else\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !predicate(value)).Concat(deleteCookies).ToArray());\n            }\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"options\"></param>\n        public void Delete(string key, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n\n            Func<string, bool> rejectPredicate;\n            if (domainHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"domain=\" + options.Domain, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else if (pathHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"path=\" + options.Path, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else\n            {\n                rejectPredicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n            }\n\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues != null)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !rejectPredicate(value)).ToArray());\n            }\n\n            Append(key, string.Empty, new CookieOptions\n            {\n                Path = options.Path,\n                Domain = options.Domain,\n                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),\n            });\n        }\n    }\n\n\n    static partial class IOwinResponseExtension \n    {\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"response\">The owin response</param>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public static void OnSendingHeaders<T>(this IOwinResponse response, Action<T> callback, T state)\n        {\n            if (response == null) {\n                throw new ArgumentNullException(\"response\");\n            }\n            Action<object> innerCallback = innerState => callback((T)innerState);\n            response.OnSendingHeaders(innerCallback, state);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/EventFeed/Event.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using System;\n\n  public struct Event\n  {\n    public long SequenceNumber { get; }\n    public DateTimeOffset OccuredAt { get; }\n    public string Name { get; }\n    public object Content { get; }\n\n    public Event(\n      long sequenceNumber,\n      DateTimeOffset occuredAt,\n      string name,\n      object content)\n    {\n      this.SequenceNumber = sequenceNumber;\n      this.OccuredAt = occuredAt;\n      this.Name = name;\n      this.Content = content;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/EventFeed/EventStore.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Threading;\n#if net461\n  using global::EventStore.ClientAPI;\n#endif\n  public class EventStore : IEventStore\n  {\n    private static long currentSequenceNumber = 0;\n    private static readonly IList<Event> database = new List<Event>();\n#if net461\n    private const string connectionString =\n     \"ConnectTo=discover://admin:changeit@127.0.0.1:2112/\";\n    private IEventStoreConnection connection =\n      EventStoreConnection.Create(connectionString);\n#endif\n    public IEnumerable<Event> GetEvents(\n      long firstEventSequenceNumber,\n      long lastEventSequenceNumber) \n      => database\n          .Where(e =>\n            e.SequenceNumber >= firstEventSequenceNumber &&\n            e.SequenceNumber <= lastEventSequenceNumber)\n          .OrderBy(e => e.SequenceNumber);\n\n    public void Raise(string eventName, object content)\n    {\n      var seqNumber = Interlocked.Increment(ref currentSequenceNumber);\n      database.Add(\n        new Event(\n          seqNumber,\n          DateTimeOffset.UtcNow,\n          eventName,\n          content));\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/EventFeed/EventsFeedModule.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using Nancy;\n\n  public class EventsFeedModule : NancyModule\n  {\n    public EventsFeedModule(IEventStore eventStore) : base(\"/events\")\n    {\n      Get(\"/\", _ =>\n      {\n        long firstEventSequenceNumber, lastEventSequenceNumber;\n        if (!long.TryParse(this.Request.Query.start.Value, \n          out firstEventSequenceNumber))\n          firstEventSequenceNumber = 0;\n        if (!long.TryParse(this.Request.Query.end.Value, \n          out lastEventSequenceNumber))\n          lastEventSequenceNumber = long.MaxValue;\n\n        return \n          eventStore.GetEvents(\n            firstEventSequenceNumber,\n            lastEventSequenceNumber);\n      });\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/EventFeed/IEventStore.cs",
    "content": "﻿using System.Collections.Generic;\nusing ShoppingCart.ShoppingCart;\n\nnamespace ShoppingCart.EventFeed\n{\n  public interface IEventStore\n  {\n    IEnumerable<Event> GetEvents(long firstEventSequenceNumber, long lastEventSequenceNumber);\n    void Raise(string eventName, object content);\n  }\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/ICache.cs",
    "content": "namespace ShoppingCart\n{\n    using System;\n    using System.Collections.Concurrent;\n    using System.Collections.Generic;\n\n  public interface ICache  \n  {\n    void Add(string key, object value, TimeSpan ttl);\n    object Get(string productsResource);\n  }\n\n  public class Cache : ICache\n  {\n    private static IDictionary<string, Tuple<DateTimeOffset, object>> cache = new ConcurrentDictionary<string, Tuple<DateTimeOffset, object>>();      \n      \n    public void Add(string key, object value, TimeSpan ttl)\n    {\n      cache[key] = Tuple.Create(DateTimeOffset.UtcNow.Add(ttl), value);\n    }\n\n    public object Get(string productsResource)\n    {\n      Tuple<DateTimeOffset, object> value;\n      if (cache.TryGetValue(productsResource, out value) && value.Item1 > DateTimeOffset.UtcNow)\n        return value;\n      cache.Remove(productsResource);\n      return null;\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/IProductCatalogueClient.cs",
    "content": "﻿namespace ShoppingCart\n{\n  using System.Collections.Generic;\n  using System.Threading.Tasks;\n  using ShoppingCart;\n\n  public interface IProductCatalogueClient\n  {\n    Task<IEnumerable<ShoppingCartItem>>\n      GetShoppingCartItems(int[] productCatalogueIds);\n  }\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/LoggingMiddleware.cs",
    "content": "namespace ShoppingCart.Infrastructure\n{\n  using System;\n  using System.Diagnostics;\n  using LibOwin;\n  using Serilog;\n  using Serilog.Context;\n\n  using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;\n\n  public class RequestLogging\n  {\n    public static AppFunc Middleware(AppFunc next, ILogger log)\n    {\n      return async env => \n      {\n        var owinContext = new OwinContext(env);\n        log.Information(\n          \"Incoming request: {@Method}, {@Path}, {@Headers}\", \n          owinContext.Request.Method,\n          owinContext.Request.Path,\n          owinContext.Request.Headers);\n        await next(env);\n        log.Information(\n          \"Outgoing response: {@StatucCode}, {@Headers}\",\n           owinContext.Response.StatusCode,\n           owinContext.Response.Headers);\n      };\n    }\n  }\n  \n  public class PerformanceLogging\n  {\n    public static AppFunc Middleware(AppFunc next, ILogger log)\n    {\n      return async env => \n      {\n        var stopWatch = new Stopwatch();\n        stopWatch.Start();\n        await next(env);\n        stopWatch.Stop();\n        var owinContext = new OwinContext(env);\n        log.Information(\n          \"Request: {@Method} {@Path} executed in {RequestTime:000} ms\",\n          owinContext.Request.Method, owinContext.Request.Path, \n          stopWatch.ElapsedMilliseconds);\n      };\n    }\n  }\n  \n  public class CorrelationToken\n  {\n    public static AppFunc Middleware(AppFunc next)\n    {\n      return async env => \n      {\n        Guid correlationToken;\n        var owinContext = new OwinContext(env);\n        if (!(owinContext.Request.Headers[\"Correlation-Token\"] != null\n            && Guid.TryParse(owinContext.Request.Headers[\"Correlation-Token\"], out correlationToken)))\n          correlationToken = Guid.NewGuid();\n\n        owinContext.Set(\"correlationToken\", correlationToken.ToString());  \n        using (LogContext.PushProperty(\"CorrelationToken\", correlationToken))\n          await next(env);\n      };\n    }    \n  }\n    \n  public class GlobalErrorLogging\n  {\n    public static AppFunc Middleware(AppFunc next, ILogger log)\n    {\n      return async env =>\n      {\n        try\n        {\n          await next(env);  \n        }\n        catch (Exception ex)\n        {\n          log.Error(ex, \"Unhandled exception\");\n        }\n      };\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/MonitoringMiddleware.cs",
    "content": "namespace ShoppingCart.Infrastructure\n{\n    using System;\n    using System.Collections.Generic;\n    using System.Threading.Tasks;\n    using LibOwin;\n\n    using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;\n\n  public class MonitoringMiddleware\n  {\n    private AppFunc next;\n    private Func<Task<bool>> healthCheck;\n    \n    private static readonly PathString monitorPath = new PathString(\"/_monitor\");\n    private static readonly PathString monitorShallowPath = new PathString(\"/_monitor/shallow\");\n    private static readonly PathString monitorDeepPath = new PathString(\"/_monitor/deep\");\n\n    public MonitoringMiddleware(AppFunc next, Func<Task<bool>> healthCheck)\n    {\n      this.next = next;\n      this.healthCheck = healthCheck;\n    }\n    \n    public Task Invoke(IDictionary<string, object> env)\n    {\n      var context = new OwinContext(env);\n      if (context.Request.Path.StartsWithSegments(monitorPath))\n        return HandleMonitorEndpoint(context);\n      else\n        return this.next(env); \n    }\n\n    private Task HandleMonitorEndpoint(OwinContext context)\n    {\n      if (context.Request.Path.StartsWithSegments(monitorShallowPath))\n        return ShallowEndpoint(context);\n      else if (context.Request.Path.StartsWithSegments(monitorDeepPath))\n        return DeepEndpoint(context);\n      return Task.FromResult(0);\n    }\n\n    private async Task DeepEndpoint(OwinContext context)\n    {\n      if (await this.healthCheck())\n        context.Response.StatusCode = 204;\n      else\n        context.Response.StatusCode = 503;\n    }\n\n    private Task ShallowEndpoint(OwinContext context)\n    {\n      context.Response.StatusCode = 204;\n      return Task.FromResult(0);\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/ProductCatalogueClient.cs",
    "content": "﻿namespace ShoppingCart\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Threading.Tasks;\n  using System.Net.Http;\n  using System.Threading;\n  using Newtonsoft.Json;\n  using Polly;\n  using ShoppingCart;\n\n  public class ProductCatalogueClient : IProductCatalogueClient\n  {\n    private static Policy exponentialRetryPolicy =\n      Policy\n        .Handle<Exception>()\n        .WaitAndRetryAsync(\n          3, \n          attempt => TimeSpan.FromMilliseconds(100 * Math.Pow(2, attempt)), (ex, _) => Console.WriteLine(ex.ToString()));\n\n    private static string productCatalogueBaseUrl =\n      @\"http://private-05cc8-chapter2productcataloguemicroservice.apiary-mock.com\";\n    private static string getProductPathTemplate =\n      \"/products?productIds=[{0}]\";\n\n    public Task<IEnumerable<ShoppingCartItem>>\n      GetShoppingCartItems(int[] productCatalogueIds) =>\n      exponentialRetryPolicy\n        .ExecuteAsync(() => GetItemsFromCatalogueService(productCatalogueIds));\n\n    private async Task<IEnumerable<ShoppingCartItem>>\n      GetItemsFromCatalogueService(int[] productCatalogueIds)\n    {\n      var response = await\n        RequestProductFromProductCatalogue(productCatalogueIds).ConfigureAwait(false);\n      return await ConvertToShoppingCartItems(response).ConfigureAwait(false);\n    }\n\n    private static async Task<HttpResponseMessage> RequestProductFromProductCatalogue(int[] productCatalogueIds)\n    {\n      var productsResource = string.Format(\n        getProductPathTemplate, string.Join(\",\", productCatalogueIds));\n      using (var httpClient = new HttpClient())\n      {\n        httpClient.BaseAddress = new Uri(productCatalogueBaseUrl);\n        return await httpClient.GetAsync(productsResource).ConfigureAwait(false);\n      }\n    }\n\n    private static async Task<IEnumerable<ShoppingCartItem>> ConvertToShoppingCartItems(HttpResponseMessage response)\n    {\n      response.EnsureSuccessStatusCode();\n      var products = \n        JsonConvert.DeserializeObject<List<ProductCatalogueProduct>>(await response.Content.ReadAsStringAsync().ConfigureAwait(false));\n      return\n        products\n          .Select(p => new ShoppingCartItem(\n            int.Parse(p.ProductId),\n            p.ProductName,\n            p.ProductDescription,\n            p.Price\n        ));\n    }\n\n    private class ProductCatalogueProduct\n    {\n      public string ProductId { get; set; }\n      public string ProductName { get; set; }\n      public string ProductDescription { get; set; }\n      public Money Price { get; set; }\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/Program.cs",
    "content": "using System.IO;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace ShoppingCart\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"ShoppingCart\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/ShoppingCart/IShoppingCartStore.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  public interface IShoppingCartStore\n  {\n    ShoppingCart Get(int userId);\n    void Save(ShoppingCart shoppingCart);\n  }\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/ShoppingCart/ShoppingCart.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using System.Collections.Generic;\n  using System.Linq;\n  using global::ShoppingCart.EventFeed;\n\n  public class ShoppingCart\n  {\n    private HashSet<ShoppingCartItem> items = new HashSet<ShoppingCartItem>();\n\n    public int UserId { get; }\n    public IEnumerable<ShoppingCartItem> Items { get { return items; } }\n\n    public ShoppingCart(int userId)\n    {\n      this.UserId = userId;\n    }\n\n    public void AddItems(\n      IEnumerable<ShoppingCartItem> shoppingCartItems,\n      IEventStore eventStore)\n    {\n      foreach (var item in shoppingCartItems)\n        if (this.items.Add(item))\n          eventStore.Raise(\n            \"ShoppingCartItemAdded\",\n            new { UserId, item });\n    }\n\n    public void RemoveItems(\n      int[] productCatalogueIds,\n      IEventStore eventStore)\n    {\n      items.RemoveWhere(i => productCatalogueIds.Contains(i.ProductCatalogueId));\n    }\n  }\n\n  public class ShoppingCartItem\n  {\n    public int ProductCatalogueId { get; }\n    public string ProductName { get; }\n    public string Desscription { get; }\n    public Money Price { get; }\n\n    public ShoppingCartItem(\n      int productCatalogueId,\n      string productName,\n      string description,\n      Money price)\n    {\n      this.ProductCatalogueId = productCatalogueId;\n      this.ProductName = productName;\n      this.Desscription = description;\n      this.Price = price;\n    }\n\n    public override bool Equals(object obj)\n    {\n      if (obj == null || GetType() != obj.GetType())\n      {\n        return false;\n      }\n\n      var that = obj as ShoppingCartItem;\n      return this.ProductCatalogueId.Equals(that.ProductCatalogueId);\n    }\n\n    // override object.GetHashCode\n    public override int GetHashCode()\n    {\n      return this.ProductCatalogueId.GetHashCode();\n    }\n  }\n\n  public class Money\n  {\n    public string Currency { get; }\n    public decimal Amount { get; }\n\n    public Money(string currency, decimal amount)\n    {\n      this.Currency = currency;\n      this.Amount = amount;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/ShoppingCart/ShoppingCartModule.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using EventFeed;\n  using Nancy;\n  using Nancy.ModelBinding;\n\n  public class ShoppingCartModule : NancyModule\n  {\n    public ShoppingCartModule(\n      IShoppingCartStore shoppingCartStore,\n      IProductCatalogueClient productCatalogue,\n      IEventStore eventStore) \n      : base(\"/shoppingcart\")\n    {\n      Get(\"/{userid:int}\", parameters =>\n      {\n        var userId = (int) parameters.userid;\n        return shoppingCartStore.Get(userId);\n      });\n\n      Post(\"/{userid:int}/items\", async (parameters, _) =>\n      {\n        var productCatalogueIds = this.Bind<int[]>();\n        var userId = (int) parameters.userid;\n\n        var shoppingCart = shoppingCartStore.Get(userId);\n        var shoppingCartItems = await productCatalogue.GetShoppingCartItems(productCatalogueIds).ConfigureAwait(false);\n        shoppingCart.AddItems(shoppingCartItems, eventStore);\n        shoppingCartStore.Save(shoppingCart);\n\n        return shoppingCart;\n      });\n\n      Delete(\"/{userid:int}/items\", parameters =>\n      {\n        var productCatalogueIds = this.Bind<int[]>();\n        var userId = (int)parameters.userid;\n\n        var shoppingCart = shoppingCartStore.Get(userId);\n        shoppingCart.RemoveItems(productCatalogueIds, eventStore);\n        shoppingCartStore.Save(shoppingCart);\n\n        return shoppingCart;\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/ShoppingCart/ShoppingCartStore.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using System.Collections.Generic;\n\n  public class ShoppingCartStore : IShoppingCartStore\n  {\n    private static readonly Dictionary<int, ShoppingCart> database = new Dictionary<int, ShoppingCart>();\n\n    public ShoppingCart Get(int userId)\n    {\n      if (!database.ContainsKey(userId))\n        database[userId] = new ShoppingCart(userId);\n      return database[userId];\n    }\n\n    public void Save(ShoppingCart shoppingCart)\n    {\n      // Nothing needed. Saving would be needed with a real DB\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter09/ShoppingCart/ShoppingCart.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>10e4f601-c16b-4936-a7b4-d32d799318d1</ProjectGuid>\n    <RootNamespace>ShoppingCart</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter09/ShoppingCart/Startup.cs",
    "content": "namespace ShoppingCart\n{\n    using System;\n    using System.Data.SqlClient;\n    using System.Threading.Tasks;\n    using Microsoft.AspNetCore.Builder;\n    using System.Linq;\n    using Dapper;\n    using Nancy.Owin;\n    using Serilog;\n    using global::ShoppingCart.Infrastructure;\n    using Nancy;\n    using Nancy.Bootstrapper;\n    using Nancy.TinyIoc;\n    using System.Net.Http;\n    using Serilog.Events;\n\n  public interface IHttpClientFactory\n  {\n    HttpClient Create(Uri uri);\n  }\n\n  public class HttpClientFactory : IHttpClientFactory\n  {\n    private readonly string correlationToken;\n\n    public HttpClientFactory(string correlationToken)\n    {\n      this.correlationToken = correlationToken;\n    }\n\n    public HttpClient Create(Uri uri)\n    {\n      var client = new HttpClient() { BaseAddress = uri } ;\n      client.DefaultRequestHeaders.Add(\"Correlation-Token\", this.correlationToken);\n      return client;\n    }\n  }\n\n  public class Bootstrapper : DefaultNancyBootstrapper\n  {\n    private readonly ILogger log;\n\n    public Bootstrapper(ILogger log)\n    {\n      this.log = log;\n    }\n\n    protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)\n    {\n      base.ApplicationStartup(container, pipelines);\n      container.Register(this.log);\n    }\n\n    protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)\n    {\n      base.RequestStartup(container, pipelines, context);\n      var correlationToken = context.GetOwinEnvironment()[\"correlationToken\"] as string;\n      container.Register<IHttpClientFactory>(new HttpClientFactory(correlationToken));\n    }\n  }\n\n  public class Startup\n  {\n    public void Configure(IApplicationBuilder app)\n    {\n      var log = ConfigureLogger();\n      \n      app.UseOwin(buildFunc => \n      {\n        buildFunc(next => GlobalErrorLogging.Middleware(next, log));\n        buildFunc(next => CorrelationToken.Middleware(next));\n        buildFunc(next => RequestLogging.Middleware(next, log));\n        buildFunc(next => PerformanceLogging.Middleware(next, log));\n        buildFunc(next => new MonitoringMiddleware(next, HealthCheck).Invoke);\n        buildFunc.UseNancy(opt => opt.Bootstrapper = new Bootstrapper(log));\n      });\n    }\n\n    private ILogger ConfigureLogger()\n    {      \n      return new LoggerConfiguration()\n        .Enrich.FromLogContext()\n        .WriteTo.ColoredConsole(\n           LogEventLevel.Verbose,\n           \"{NewLine}{Timestamp:HH:mm:ss} [{Level}] ({CorrelationToken}) {Message}{NewLine}{Exception}\")\n        .CreateLogger();\n    }\n\n    private const string connectionString = @\"Data Source=.\\SQLEXPRESS;Initial Catalog=ShoppingCart;Integrated Security=True\";\n    private readonly int threshold = 1000;\n    \n    public async Task<bool> HealthCheck()\n    {\n      using (var conn = new SqlConnection(connectionString))\n      {\n        var count = (await conn.QueryAsync<int>(\"select count(ID) from ShoppingCart\")).Single();\n        return count > this.threshold;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/database-scripts/create-shopping-cart-db.sql",
    "content": "CREATE DATABASE ShoppingCart\nGO\n\nUSE [ShoppingCart]\nGO\n\nCREATE TABLE [dbo].[ShoppingCart](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n  [UserId] [bigint] NOT NULL,\n  CONSTRAINT ShoppingCartUnique UNIQUE([ID], [UserID])\n)\nGO\n\nCREATE INDEX ShoppingCart_UserId \nON [dbo].[ShoppingCart] (UserId)\nGO\n\nCREATE TABLE [dbo].[ShoppingCartItems](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n\t[ShoppingCartId] [int] NOT NULL,\n\t[ProductCatalogId] [bigint] NOT NULL,\n\t[ProductName] [nvarchar](100) NOT NULL,\n\t[ProductDescription] [nvarchar](500) NULL,\n\t[Amount] [int] NOT NULL,\n\t[Currency] [nvarchar](5) NOT NULL\n)\n\nGO\n\nALTER TABLE [dbo].[ShoppingCartItems]  WITH CHECK ADD CONSTRAINT [FK_ShoppingCart] FOREIGN KEY([ShoppingCartId])\nREFERENCES [dbo].[ShoppingCart] ([Id])\nGO\n\nALTER TABLE [dbo].[ShoppingCartItems] CHECK CONSTRAINT [FK_ShoppingCart]\nGO\n\nCREATE INDEX ShoppingCartItems_ShoppingCartId \nON [dbo].[ShoppingCartItems] (ShoppingCartId)\nGO\n\nCREATE TABLE [dbo].[EventStore](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n  [Name] [nvarchar](100)  NOT NULL,\n  [OccuredAt] [datetimeoffset] NOT NULL,\n  [Content][nvarchar](max) NOT NULL\n)\nGO\n\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"Polly\": \"4.2.1\",\n    \"Dapper\": \"1.50.0-rc2a\",\n    \"Serilog\": \"2.0.0-rc-600\",\n    \"Serilog.Sinks.ColoredConsole\": \"2.0.0-beta-1001\"\n  },\n  \"runtimes\": {\n    \"win10-x64\": \"\"\n  },\n\n  \"tools\": {\n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ],\n      \"dependencies\": {\n        \"System.Net.Http\": \"4.0.1-rc2-24027\"\n      }\n    },\n    \"net461\": {\n      \"buildOptions\": {\"define\": [\"net461\"]},\n      \"frameworkAssemblies\": {\n        \"System.Net.Http\": \"4.0.0.0\",\n        \"System.Runtime\": \"4.0.20.0\"\n      },\n      \"dependencies\": {\n        \"EventStore.Client\": \"3.3.1\",\n        \"Microsoft.CSharp\": \"4.0.0\"\n      }\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"HelloMicroservices\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter09/ShoppingCart/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter11/.idea.ch11/riderModule.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"RIDER_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\">\n    <content url=\"file://$MODULE_DIR$/..\">\n      <sourceFolder url=\"file://$MODULE_DIR$/..\" isTestSource=\"false\" />\n    </content>\n    <content url=\"file://C:/projects/Nancy/src/Nancy\">\n      <sourceFolder url=\"file://C:/projects/Nancy/src/Nancy\" isTestSource=\"false\" />\n    </content>\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n  </component>\n</module>"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/HelloMicroservicesPlatform.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>daebd923-b213-4ca5-a240-b96686aec974</ProjectGuid>\n    <RootNamespace>HelloMicroservicesPlatform</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace HelloMicroservicesPlatform\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"HelloMicroservicesPlatform\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/Startup.cs",
    "content": "namespace HelloMicroservicesPlatform\n{\n  using System;\n  using System.Threading.Tasks;\n  using Microsoft.AspNetCore.Builder;\n  using MicroserviceNET.Logging;\n  using MicroserviceNET.Auth;\n  using MicroserviceNET.Platform;\n  using Serilog;\n  using Serilog.Events;\n  using Nancy;\n  using Nancy.Owin;\n  using Nancy.TinyIoc;\n  using Nancy.Bootstrapper;\n\n  public class Startup\n  {\n    public void Configure(IApplicationBuilder app)\n    {\n      app.UseOwin()\n         .UseMonitoringAndLogging(ConfigureLogger(), HealthCheck)\n         .UseAuthPlatform(\"test-scope\")\n         .UseNancy();\n    }\n\n\n    private ILogger ConfigureLogger()\n    {\n      return new LoggerConfiguration()\n        .Enrich.FromLogContext()\n        .WriteTo.ColoredConsole(\n                                LogEventLevel.Verbose,\n                                \"{NewLine}{Timestamp:HH:mm:ss} [{Level}] ({CorrelationToken}) {Message}{NewLine}{Exception}\")\n        .CreateLogger();\n      }\n\n    private static Task<bool> HealthCheck()\n    {\n      return Task.FromResult(true);\n    }\n  }\n\n  public class Bootstrapper : DefaultNancyBootstrapper\n  {\n    protected override void RequestStartup(\n      TinyIoCContainer container,\n      IPipelines pipelines,\n      NancyContext context)\n    {\n      base.RequestStartup(container, pipelines, context);\n      container.UseHttpClientFactory(context);\n    }\n  }\n\n  public class Hello : NancyModule\n  {\n    public Hello(IHttpClientFactory clientFactory)\n    {\n      Get(\"/\", async (_, __) =>\n      {\n        var client = await\n        clientFactory.Create(\n          new Uri(\"http://otherservice/\"),\n          \"scope_for_other_microservice\");\n        var resp = await\n          client.GetAsync(\"/some/path\").ConfigureAwait(false);\n        return resp.StatusCode;\n      });\n    }\n  }\n}\n\n"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Serilog\": \"2.0.0-rc-600\",\n    \"MicroserviceNET.Platform\": { \"target\": \"project\" },\n    \"Serilog.Sinks.ColoredConsole\": \"2.0.0-beta-700\"\n  },\n\n  \"tools\": {                                                                  \n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"HelloMicroservicesPlatform\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter11/HelloMicroservicesPlatform/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter11/MicroserivceNET.Auth/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter11/MicroserivceNET.Auth/Application_Packages/LibOwin.cs",
    "content": "﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.\n// Copyright (c) Damian Hickey. All rights reserved. See License.txt in the project root for license information.\n\n// https://github.com/damianh/LibOwin\n// Modifying this file may result in difficulties when upgrading the package.\n// All types are internal. Add a LIBOWIN_PUBLIC compilation symbol to make them public.\n\nnamespace LibOwin.Infrastructure\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Linq;\n\n    internal static partial class Constants\n    {\n        internal const string Https = \"HTTPS\";\n\n        internal const string HttpDateFormat = \"r\";\n\n        internal static partial class Headers\n        {\n            internal const string ContentType = \"Content-Type\";\n            internal const string CacheControl = \"Cache-Control\";\n            internal const string MediaType = \"Media-Type\";\n            internal const string Accept = \"Accept\";\n            internal const string Host = \"Host\";\n            internal const string ETag = \"ETag\";\n            internal const string Location = \"Location\";\n            internal const string ContentLength = \"Content-Length\";\n            internal const string SetCookie = \"Set-Cookie\";\n            internal const string Expires = \"Expires\";\n        }\n    }\n\n    internal struct HeaderSegment : IEquatable<HeaderSegment>\n    {\n        private readonly StringSegment _formatting;\n        private readonly StringSegment _data;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public HeaderSegment(StringSegment formatting, StringSegment data)\n        {\n            _formatting = formatting;\n            _data = data;\n        }\n\n        public StringSegment Formatting\n        {\n            get { return _formatting; }\n        }\n\n        public StringSegment Data\n        {\n            get { return _data; }\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegment other)\n        {\n            return _formatting.Equals(other._formatting) && _data.Equals(other._data);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegment && Equals((HeaderSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return (_formatting.GetHashCode() * 397) ^ _data.GetHashCode();\n            }\n        }\n\n        public static bool operator ==(HeaderSegment left, HeaderSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegment left, HeaderSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n    }\n\n    internal struct HeaderSegmentCollection : IEnumerable<HeaderSegment>, IEquatable<HeaderSegmentCollection>\n    {\n        private readonly string[] _headers;\n\n        public HeaderSegmentCollection(string[] headers)\n        {\n            _headers = headers;\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegmentCollection other)\n        {\n            return Equals(_headers, other._headers);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegmentCollection && Equals((HeaderSegmentCollection)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return (_headers != null ? _headers.GetHashCode() : 0);\n        }\n\n        public static bool operator ==(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public Enumerator GetEnumerator()\n        {\n            return new Enumerator(_headers);\n        }\n\n        IEnumerator<HeaderSegment> IEnumerable<HeaderSegment>.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        internal struct Enumerator : IEnumerator<HeaderSegment>\n        {\n            private readonly string[] _headers;\n            private int _index;\n\n            private string _header;\n            private int _headerLength;\n            private int _offset;\n\n            private int _leadingStart;\n            private int _leadingEnd;\n            private int _valueStart;\n            private int _valueEnd;\n            private int _trailingStart;\n\n            private Mode _mode;\n\n            private static readonly string[] NoHeaders = new string[0];\n\n            public Enumerator(string[] headers)\n            {\n                _headers = headers ?? NoHeaders;\n                _header = string.Empty;\n                _headerLength = -1;\n                _index = -1;\n                _offset = -1;\n                _leadingStart = -1;\n                _leadingEnd = -1;\n                _valueStart = -1;\n                _valueEnd = -1;\n                _trailingStart = -1;\n                _mode = Mode.Leading;\n            }\n\n            private enum Mode\n            {\n                Leading,\n                Value,\n                ValueQuoted,\n                Trailing,\n                Produce,\n            }\n\n            private enum Attr\n            {\n                Value,\n                Quote,\n                Delimiter,\n                Whitespace\n            }\n\n            public HeaderSegment Current\n            {\n                get\n                {\n                    return new HeaderSegment(\n                        new StringSegment(_header, _leadingStart, _leadingEnd - _leadingStart),\n                        new StringSegment(_header, _valueStart, _valueEnd - _valueStart));\n                }\n            }\n\n            object IEnumerator.Current\n            {\n                get { return Current; }\n            }\n\n            public void Dispose()\n            {\n            }\n\n            public bool MoveNext()\n            {\n                while (true)\n                {\n                    if (_mode == Mode.Produce)\n                    {\n                        _leadingStart = _trailingStart;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        if (_offset == _headerLength &&\n                            _leadingStart != -1 &&\n                            _leadingStart != _offset)\n                        {\n                            // Also produce trailing whitespace\n                            _leadingEnd = _offset;\n                            return true;\n                        }\n                        _mode = Mode.Leading;\n                    }\n\n                    // if end of a string\n                    if (_offset == _headerLength)\n                    {\n                        ++_index;\n                        _offset = -1;\n                        _leadingStart = 0;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        // if that was the last string\n                        if (_index == _headers.Length)\n                        {\n                            // no more move nexts\n                            return false;\n                        }\n\n                        // grab the next string\n                        _header = _headers[_index] ?? string.Empty;\n                        _headerLength = _header.Length;\n                    }\n                    while (true)\n                    {\n                        ++_offset;\n                        char ch = _offset == _headerLength ? (char)0 : _header[_offset];\n                        // todo - array of attrs\n                        Attr attr = char.IsWhiteSpace(ch) ? Attr.Whitespace : ch == '\\\"' ? Attr.Quote : (ch == ',' || ch == (char)0) ? Attr.Delimiter : Attr.Value;\n\n                        switch (_mode)\n                        {\n                            case Mode.Leading:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _leadingEnd = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Value:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Delimiter:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Value:\n                                        // more\n                                        break;\n                                    case Attr.Whitespace:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Trailing;\n                                        break;\n                                }\n                                break;\n                            case Mode.ValueQuoted:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Delimiter:\n                                        if (ch == (char)0)\n                                        {\n                                            _valueEnd = _offset;\n                                            _trailingStart = _offset;\n                                            _mode = Mode.Produce;\n                                        }\n                                        break;\n                                    case Attr.Value:\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Trailing:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                        }\n                        if (_mode == Mode.Produce)\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n\n            public void Reset()\n            {\n                _index = 0;\n                _offset = 0;\n                _leadingStart = 0;\n                _leadingEnd = 0;\n                _valueStart = 0;\n                _valueEnd = 0;\n            }\n        }\n    }\n\n    internal struct StringSegment : IEquatable<StringSegment>\n    {\n        private readonly string _buffer;\n        private readonly int _offset;\n        private readonly int _count;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public StringSegment(string buffer, int offset, int count)\n        {\n            _buffer = buffer;\n            _offset = offset;\n            _count = count;\n        }\n\n        public string Buffer\n        {\n            get { return _buffer; }\n        }\n\n        public int Offset\n        {\n            get { return _offset; }\n        }\n\n        public int Count\n        {\n            get { return _count; }\n        }\n\n        public string Value\n        {\n            get { return _offset == -1 ? null : _buffer.Substring(_offset, _count); }\n        }\n\n        public bool HasValue\n        {\n            get { return _offset != -1 && _count != 0 && _buffer != null; }\n        }\n\n        #region Equality members\n\n        public bool Equals(StringSegment other)\n        {\n            return string.Equals(_buffer, other._buffer) && _offset == other._offset && _count == other._count;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is StringSegment && Equals((StringSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hashCode = (_buffer != null ? _buffer.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ _offset;\n                hashCode = (hashCode * 397) ^ _count;\n                return hashCode;\n            }\n        }\n\n        public static bool operator ==(StringSegment left, StringSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(StringSegment left, StringSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public bool StartsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool EndsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset + _count - textLength, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool Equals(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count != textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public string Substring(int offset, int length)\n        {\n            return _buffer.Substring(_offset + offset, length);\n        }\n\n        public StringSegment Subsegment(int offset, int length)\n        {\n            return new StringSegment(_buffer, _offset + offset, length);\n        }\n\n        public override string ToString()\n        {\n            return Value ?? string.Empty;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AddCookieCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, string>)state;\n            if (!dictionary.ContainsKey(name))\n            {\n                dictionary.Add(name, value);\n            }\n        };\n\n        private static readonly char[] SemicolonAndComma = new[] { ';', ',' };\n\n        internal static IDictionary<string, string> GetCookies(IOwinRequest request)\n        {\n            var cookies = request.Get<IDictionary<string, string>>(\"Microsoft.Owin.Cookies#dictionary\");\n            if (cookies == null)\n            {\n                cookies = new Dictionary<string, string>(StringComparer.Ordinal);\n                request.Set(\"Microsoft.Owin.Cookies#dictionary\", cookies);\n            }\n\n            string text = GetHeader(request.Headers, \"Cookie\");\n            if (request.Get<string>(\"Microsoft.Owin.Cookies#text\") != text)\n            {\n                cookies.Clear();\n                ParseDelimited(text, SemicolonAndComma, AddCookieCallback, cookies);\n                request.Set(\"Microsoft.Owin.Cookies#text\", text);\n            }\n            return cookies;\n        }\n\n        internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)\n        {\n            int textLength = text.Length;\n            int equalIndex = text.IndexOf('=');\n            if (equalIndex == -1)\n            {\n                equalIndex = textLength;\n            }\n            int scanIndex = 0;\n            while (scanIndex < textLength)\n            {\n                int delimiterIndex = text.IndexOfAny(delimiters, scanIndex);\n                if (delimiterIndex == -1)\n                {\n                    delimiterIndex = textLength;\n                }\n                if (equalIndex < delimiterIndex)\n                {\n                    while (scanIndex != equalIndex && char.IsWhiteSpace(text[scanIndex]))\n                    {\n                        ++scanIndex;\n                    }\n                    string name = text.Substring(scanIndex, equalIndex - scanIndex);\n                    string value = text.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);\n                    callback(\n                        Uri.UnescapeDataString(name.Replace('+', ' ')),\n                        Uri.UnescapeDataString(value.Replace('+', ' ')),\n                        state);\n                    equalIndex = text.IndexOf('=', delimiterIndex);\n                    if (equalIndex == -1)\n                    {\n                        equalIndex = textLength;\n                    }\n                }\n                scanIndex = delimiterIndex + 1;\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        public static string GetHeader(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        public static IEnumerable<string> GetHeaderSplit(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : GetHeaderSplitImplementation(values);\n        }\n\n        private static IEnumerable<string> GetHeaderSplitImplementation(string[] values)\n        {\n            foreach (var segment in new HeaderSegmentCollection(values))\n            {\n                if (segment.Data.HasValue)\n                {\n                    yield return DeQuote(segment.Data.Value);\n                }\n            }\n        }\n\n        public static string[] GetHeaderUnmodified(IDictionary<string, string[]> headers, string key)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            string[] values;\n            return headers.TryGetValue(key, out values) ? values : null;\n        }\n\n        public static void SetHeader(IDictionary<string, string[]> headers, string key, string value)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { value };\n            }\n        }\n\n        public static void SetHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        // Quote items that contain comas and are not already quoted.\n        private static string QuoteIfNeeded(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Contains(','))\n            {\n                if (value[0] != '\"' || value[value.Length - 1] != '\"')\n                {\n                    value = '\"' + value + '\"';\n                }\n            }\n\n            return value;\n        }\n\n        private static string DeQuote(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Length > 1 && value[0] == '\"' && value[value.Length - 1] == '\"')\n            {\n                value = value.Substring(1, value.Length - 2);\n            }\n\n            return value;\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = values;\n            }\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, IEnumerable<string> values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            headers[key] = values.ToArray();\n        }\n\n        public static void AppendHeader(IDictionary<string, string[]> headers, string key, string values)\n        {\n            if (string.IsNullOrWhiteSpace(values))\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeader(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + values };\n            }\n        }\n\n        public static void AppendHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeaderJoined(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        public static void AppendHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string[] existing = GetHeaderUnmodified(headers, key);\n            if (existing == null)\n            {\n                SetHeaderUnmodified(headers, key, values);\n            }\n            else\n            {\n                SetHeaderUnmodified(headers, key, existing.Concat(values));\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AppendItemCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, List<String>>)state;\n\n            List<string> existing;\n            if (!dictionary.TryGetValue(name, out existing))\n            {\n                dictionary.Add(name, new List<string>(1) { value });\n            }\n            else\n            {\n                existing.Add(value);\n            }\n        };\n\n        private static readonly char[] AmpersandAndSemicolon = new[] { '&', ';' };\n\n        internal static IDictionary<string, string[]> GetQuery(IOwinRequest request)\n        {\n            var query = request.Get<IDictionary<string, string[]>>(\"Microsoft.Owin.Query#dictionary\");\n            if (query == null)\n            {\n                query = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n                request.Set(\"Microsoft.Owin.Query#dictionary\", query);\n            }\n\n            string text = request.QueryString.Value;\n            if (request.Get<string>(\"Microsoft.Owin.Query#text\") != text)\n            {\n                query.Clear();\n                var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n                ParseDelimited(text, AmpersandAndSemicolon, AppendItemCallback, accumulator);\n                foreach (var kv in accumulator)\n                {\n                    query.Add(kv.Key, kv.Value.ToArray());\n                }\n                request.Set(\"Microsoft.Owin.Query#text\", text);\n            }\n            return query;\n        }\n\n        internal static IFormCollection GetForm(string text)\n        {\n            IDictionary<string, string[]> form = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n            ParseDelimited(text, new[] { '&' }, AppendItemCallback, accumulator);\n            foreach (var kv in accumulator)\n            {\n                form.Add(kv.Key, kv.Value.ToArray());\n            }\n            return new FormCollection(form);\n        }\n\n        internal static string GetJoinedValue(IDictionary<string, string[]> store, string key)\n        {\n            string[] values = GetUnmodifiedValues(store, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        internal static string[] GetUnmodifiedValues(IDictionary<string, string[]> store, string key)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n            string[] values;\n            return store.TryGetValue(key, out values) ? values : null;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        internal static string GetHost(IOwinRequest request)\n        {\n            IHeaderDictionary headers = request.Headers;\n\n            string host = GetHeader(headers, \"Host\");\n            if (!string.IsNullOrWhiteSpace(host))\n            {\n                return host;\n            }\n\n            string localIpAddress = request.LocalIpAddress ?? \"localhost\";\n            var localPort = request.Get<string>(OwinConstants.CommonKeys.LocalPort);\n            return string.IsNullOrWhiteSpace(localPort) ? localIpAddress : (localIpAddress + \":\" + localPort);\n        }\n    }\n}\n\nnamespace LibOwin\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Globalization;\n    using System.IO;\n    using System.Linq;\n    using System.Security.Claims;\n    using System.Security.Principal;\n    using System.Text;\n    using System.Threading;\n    using System.Threading.Tasks;\n    using LibOwin.Infrastructure;\n\n    #if LIBOWIN_PUBLIC\n\n    public partial class CookieOptions { }\n    public partial class FormCollection { }\n    public partial class HeaderDictionary { }\n    public partial struct HostString { }\n    public partial interface IFormCollection { }\n    public partial interface IHeaderDictionary { }\n    public partial interface IOwinContext { }\n    public partial interface IOwinRequest { }\n    public partial interface IOwinResponse { }\n    public partial interface IReadableStringCollection { }\n    public partial class OwinContext { }\n    public partial class OwinRequest { }\n    public partial class OwinResponse { }\n    public partial struct PathString { }\n    public partial struct QueryString { }\n    public partial class ReadableStringCollection { }\n    public partial class RequestCookieCollection { }\n    public partial class ResponseCookieCollection { }\n    public partial class IOwinResponseExtension { }\n\n    #endif\n\n    /// <summary>\n    /// Options used to create a new cookie.\n    /// </summary>\n    partial class CookieOptions\n    {\n        /// <summary>\n        /// Creates a default cookie with a path of '/'.\n        /// </summary>\n        public CookieOptions()\n        {\n            Path = \"/\";\n        }\n\n        /// <summary>\n        /// Gets or sets the domain to associate the cookie with.\n        /// </summary>\n        /// <returns>The domain to associate the cookie with.</returns>\n        public string Domain { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cookie path.\n        /// </summary>\n        /// <returns>The cookie path.</returns>\n        public string Path { get; set; }\n\n        /// <summary>\n        /// Gets or sets the expiration date and time for the cookie.\n        /// </summary>\n        /// <returns>The expiration date and time for the cookie.</returns>\n        public DateTime? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether to transmit the cookie using Secure Sockets Layer (SSL)—that is, over HTTPS only.\n        /// </summary>\n        /// <returns>true to transmit the cookie only over an SSL connection (HTTPS); otherwise, false.</returns>\n        public bool Secure { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether a cookie is accessible by client-side script.\n        /// </summary>\n        /// <returns>true if a cookie is accessible by client-side script; otherwise, false.</returns>\n        public bool HttpOnly { get; set; }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial class FormCollection : ReadableStringCollection, IFormCollection\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.FormCollection\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The store for the form.</param>\n        public FormCollection(IDictionary<string, string[]> store)\n            : base(store)\n        {}\n    }\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial class HeaderDictionary : IHeaderDictionary\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The underlying data store.</param>\n        public HeaderDictionary(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Gets an <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public ICollection<string> Keys\n        {\n            get { return Store.Keys; }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        public ICollection<string[]> Values\n        {\n            get { return Store.Values; }\n        }\n\n        /// <summary>\n        /// Gets the number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>The number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public int Count\n        {\n            get { return Store.Count; }\n        }\n\n        /// <summary>\n        /// Gets a value that indicates whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode.\n        /// </summary>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode; otherwise, false.</returns>\n        public bool IsReadOnly\n        {\n            get { return Store.IsReadOnly; }\n        }\n\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n            set { Set(key, value); }\n        }\n\n        /// <summary>\n        /// Throws KeyNotFoundException if the key is not present.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns></returns>\n        string[] IDictionary<string, string[]>.this[string key]\n        {\n            get { return Store[key]; }\n            set { Store[key] = value; }\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetHeader(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection without modification, or null if the key is not present.</returns>\n        public IList<string> GetValues(string key)\n        {\n            return OwinHelpers.GetHeaderUnmodified(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        public IList<string> GetCommaSeparatedValues(string key)\n        {\n            IEnumerable<string> values = OwinHelpers.GetHeaderSplit(Store, key);\n            return values == null ? null : values.ToList();\n        }\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Append(string key, string value)\n        {\n            OwinHelpers.AppendHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Set(string key, string value)\n        {\n            OwinHelpers.SetHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Adds the given header and values to the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header values.</param>\n        public void Add(string key, string[] value)\n        {\n            Store.Add(key, value);\n        }\n\n        /// <summary>\n        /// Determines whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key.\n        /// </summary>\n        /// <param name=\"key\">The key.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key; otherwise, false.</returns>\n        public bool ContainsKey(string key)\n        {\n            return Store.ContainsKey(key);\n        }\n\n        /// <summary>\n        /// Removes the given header from the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(string key)\n        {\n            return Store.Remove(key);\n        }\n\n        /// <summary>\n        /// Retrieves a value from the dictionary.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The value.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains the key; otherwise, false.</returns>\n        public bool TryGetValue(string key, out string[] value)\n        {\n            return Store.TryGetValue(key, out value);\n        }\n\n        /// <summary>\n        /// Adds a new list of items to the collection.\n        /// </summary>\n        /// <param name=\"item\">The item to add.</param>\n        public void Add(KeyValuePair<string, string[]> item)\n        {\n            Store.Add(item);\n        }\n\n        /// <summary>\n        /// Clears the entire list of objects.\n        /// </summary>\n        public void Clear()\n        {\n            Store.Clear();\n        }\n\n        /// <summary>\n        /// Returns a value indicating whether the specified object occurs within this collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object occurs within this collection; otherwise, false.</returns>\n        public bool Contains(KeyValuePair<string, string[]> item)\n        {\n            return Store.Contains(item);\n        }\n\n        /// <summary>\n        /// Copies the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> elements to a one-dimensional Array instance at the specified index.\n        /// </summary>\n        /// <param name=\"array\">The one-dimensional Array that is the destination of the specified objects copied from the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</param>\n        /// <param name=\"arrayIndex\">The zero-based index in <paramref name=\"array\" /> at which copying begins.</param>\n        public void CopyTo(KeyValuePair<string, string[]>[] array, int arrayIndex)\n        {\n            Store.CopyTo(array, arrayIndex);\n        }\n\n        /// <summary>\n        /// Removes the given item from the the collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(KeyValuePair<string, string[]> item)\n        {\n            return Store.Remove(item);\n        }\n    }\n\n    /// <summary>\n    /// Represents the host portion of a Uri can be used to construct Uri's properly formatted and encoded for use in\n    /// HTTP headers.\n    /// </summary>\n    partial struct HostString : IEquatable<HostString>\n    {\n        private readonly string _value;\n\n        /// <summary>\n        /// Creates a new HostString without modification. The value should be Unicode rather than punycode, and may have a port.\n        /// IPv4 and IPv6 addresses are also allowed, and also may have ports.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        public HostString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Returns the original value from the constructor.\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// Returns the value as normalized by ToUriComponent().\n        /// </summary>\n        /// <returns></returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Returns the value properly formatted and encoded for use in a URI in a HTTP header.\n        /// Any Unicode is converted to punycode. IPv6 addresses will have brackets added if they are missing.\n        /// </summary>\n        /// <returns></returns>\n        public string ToUriComponent()\n        {\n            int index;\n            if (string.IsNullOrEmpty(_value))\n            {\n                return string.Empty;\n            }\n            else if (_value.IndexOf('[') >= 0)\n            {\n                // IPv6 in brackets [::1], maybe with port\n                return _value;\n            }\n            else if ((index = _value.IndexOf(':')) >= 0\n                && index < _value.Length - 1\n                && _value.IndexOf(':', index + 1) >= 0)\n            {\n                // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                return \"[\" + _value + \"]\";\n            }\n            else if (index >= 0)\n            {\n                // Has a port\n                string port = _value.Substring(index);\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value, 0, index) + port;\n            }\n            else\n            {\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value);\n            }\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the given uri component.\n        /// Any punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uriComponent\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(string uriComponent)\n        {\n            if (!string.IsNullOrEmpty(uriComponent))\n            {\n                int index;\n                if (uriComponent.IndexOf('[') >= 0)\n                {\n                    // IPv6 in brackets [::1], maybe with port\n                }\n                else if ((index = uriComponent.IndexOf(':')) >= 0\n                    && index < uriComponent.Length - 1\n                    && uriComponent.IndexOf(':', index + 1) >= 0)\n                {\n                    // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                }\n                else if (uriComponent.IndexOf(\"xn--\", StringComparison.Ordinal) >= 0)\n                {\n                    // Contains punycode\n                    if (index >= 0)\n                    {\n                        // Has a port\n                        string port = uriComponent.Substring(index);\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent, 0, index) + port;\n                    }\n                    else\n                    {\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent);\n                    }\n                }\n            }\n            return new HostString(uriComponent);\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the host and port of the give Uri instance.\n        /// Punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uri\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new HostString(uri.GetComponents(\n                UriComponents.NormalizedHost | // Always convert punycode to Unicode.\n                UriComponents.HostAndPort, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Compares the equality of the Value property, ignoring case.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(HostString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares against the given object only if it is a HostString.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is HostString && Equals((HostString)obj);\n        }\n\n        /// <summary>\n        /// Gets a hash code for the value.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(HostString left, HostString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(HostString left, HostString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial interface IFormCollection : IReadableStringCollection\n    {}\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, string[]>\n    {\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        new string this[string key] { get; set; }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        IList<string> GetCommaSeparatedValues(string key);\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Append(string key, string value);\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendCommaSeparatedValues(string key, params string[] values);\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Set(string key, string value);\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetCommaSeparatedValues(string key, params string[] values);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinContext\n    {\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        IOwinRequest Request { get; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        IOwinResponse Response { get; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        TextWriter TraceOutput { get; set; }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinContext Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinRequest\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        string Method { get; set; }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        string Scheme { get; set; }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        bool IsSecure { get; }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        HostString Host { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        PathString PathBase { get; set; }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        PathString Path { get; set; }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        QueryString QueryString { get; set; }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        IReadableStringCollection Query { get; }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        Uri Uri { get; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        RequestCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        string CacheControl { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        string MediaType { get; set; }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        string Accept { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        CancellationToken CallCancelled { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        string LocalIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        int? LocalPort { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        string RemoteIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        int? RemotePort { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        ClaimsPrincipal User { get; set; }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        Task<IFormCollection> ReadFormAsync();\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinRequest Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinResponse\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        int StatusCode { get; set; }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        string ReasonPhrase { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        ResponseCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        long? ContentLength { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        DateTimeOffset? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        string ETag { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        void OnSendingHeaders(Action<object> callback, object state);\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        void Redirect(string location);\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        void Write(string text);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        void Write(byte[] data);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        void Write(byte[] data, int offset, int count);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, int offset, int count, CancellationToken token);\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinResponse Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// Accessors for headers, query, forms, etc.\n    /// </summary>\n    partial interface IReadableStringCollection : IEnumerable<KeyValuePair<string, string[]>>\n    {\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string this[string key] { get; }\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string Get(string key);\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        IList<string> GetValues(string key);\n\n        // Raw\n    }\n\n    internal static class OwinConstants\n    {\n        #region OWIN v1.0.0 - 3.2.1. Request Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string RequestScheme = \"owin.RequestScheme\";\n        public const string RequestMethod = \"owin.RequestMethod\";\n        public const string RequestPathBase = \"owin.RequestPathBase\";\n        public const string RequestPath = \"owin.RequestPath\";\n        public const string RequestQueryString = \"owin.RequestQueryString\";\n        public const string RequestProtocol = \"owin.RequestProtocol\";\n        public const string RequestHeaders = \"owin.RequestHeaders\";\n        public const string RequestBody = \"owin.RequestBody\";\n        public const string RequestUser = \"owin.RequestUser\"; //owin 1.0.1\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.2. Response Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string ResponseStatusCode = \"owin.ResponseStatusCode\";\n        public const string ResponseReasonPhrase = \"owin.ResponseReasonPhrase\";\n        public const string ResponseProtocol = \"owin.ResponseProtocol\";\n        public const string ResponseHeaders = \"owin.ResponseHeaders\";\n        public const string ResponseBody = \"owin.ResponseBody\";\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.3. Other Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string CallCancelled = \"owin.CallCancelled\";\n\n        public const string OwinVersion = \"owin.Version\";\n\n        #endregion\n\n        #region OWIN Keys for IAppBuilder.Properties\n\n        internal static class Builder\n        {\n            public const string AddSignatureConversion = \"builder.AddSignatureConversion\";\n            public const string DefaultApp = \"builder.DefaultApp\";\n        }\n\n        #endregion\n\n        #region OWIN Key Guidelines and Common Keys - 6. Common keys\n\n        // http://owin.org/spec/CommonKeys.html\n\n        internal static class CommonKeys\n        {\n            public const string ClientCertificate = \"ssl.ClientCertificate\";\n            public const string RemoteIpAddress = \"server.RemoteIpAddress\";\n            public const string RemotePort = \"server.RemotePort\";\n            public const string LocalIpAddress = \"server.LocalIpAddress\";\n            public const string LocalPort = \"server.LocalPort\";\n            public const string IsLocal = \"server.IsLocal\";\n            public const string TraceOutput = \"host.TraceOutput\";\n            public const string Addresses = \"host.Addresses\";\n            public const string AppName = \"host.AppName\";\n            public const string Capabilities = \"server.Capabilities\";\n            public const string OnSendingHeaders = \"server.OnSendingHeaders\";\n            public const string OnAppDisposing = \"host.OnAppDisposing\";\n            public const string Scheme = \"scheme\";\n            public const string Host = \"host\";\n            public const string Port = \"port\";\n            public const string Path = \"path\";\n        }\n\n        #endregion\n\n        #region SendFiles v0.3.0\n\n        // http://owin.org/extensions/owin-SendFile-Extension-v0.3.0.htm\n\n        internal static class SendFiles\n        {\n            // 3.1. Startup\n\n            public const string Version = \"sendfile.Version\";\n            public const string Support = \"sendfile.Support\";\n            public const string Concurrency = \"sendfile.Concurrency\";\n\n            // 3.2. Per Request\n\n            public const string SendAsync = \"sendfile.SendAsync\";\n        }\n\n        #endregion\n\n        #region Opaque v0.3.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class OpaqueConstants\n        {\n            // 3.1. Startup\n            public const string Version = \"opaque.Version\";\n\n            // 3.2. Per Request\n            public const string Upgrade = \"opaque.Upgrade\";\n\n            // 5. Consumption\n            public const string Stream = \"opaque.Stream\";\n            // public const string Version = \"opaque.Version\"; // redundant, declared above\n            public const string CallCancelled = \"opaque.CallCancelled\";\n        }\n\n        #endregion\n\n        #region WebSocket v0.4.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class WebSocket\n        {\n            // 3.1. Startup\n            public const string Version = \"websocket.Version\";\n\n            // 3.2. Per Request\n            public const string Accept = \"websocket.Accept\";\n\n            // 4. Accept\n            public const string SubProtocol = \"websocket.SubProtocol\";\n\n            // 5. Consumption\n            public const string SendAsync = \"websocket.SendAsync\";\n            public const string ReceiveAsync = \"websocket.ReceiveAsync\";\n            public const string CloseAsync = \"websocket.CloseAsync\";\n            // public const string Version = \"websocket.Version\"; // redundant, declared above\n            public const string CallCancelled = \"websocket.CallCancelled\";\n            public const string ClientCloseStatus = \"websocket.ClientCloseStatus\";\n            public const string ClientCloseDescription = \"websocket.ClientCloseDescription\";\n        }\n\n        #endregion\n\n        #region Security v0.1.0\n\n        // http://owin.org/extensions/owin-Security-Extension-v0.1.0.htm\n\n        internal static class Security\n        {\n            // 3.2. Per Request\n\n            public const string User = \"server.User\";\n\n            public const string Authenticate = \"security.Authenticate\";\n\n            // 3.3. Response\n\n            public const string SignIn = \"security.SignIn\";\n\n            public const string SignOut = \"security.SignOut\";\n\n            public const string SignOutProperties = \"security.SignOutProperties\";\n\n            public const string Challenge = \"security.Challenge\";\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinContext : IOwinContext\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinContext()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Create a new wrapper.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinContext(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        public virtual IOwinRequest Request { get; private set; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        public virtual IOwinResponse Response { get; private set; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        public virtual TextWriter TraceOutput\n        {\n            get { return Get<TextWriter>(OwinConstants.CommonKeys.TraceOutput); }\n            set { Set<TextWriter>(OwinConstants.CommonKeys.TraceOutput, value); }\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinContext Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinRequest : IOwinRequest\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinRequest()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Create a new environment wrapper exposing request properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinRequest(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        public virtual string Method\n        {\n            get { return Get<string>(OwinConstants.RequestMethod); }\n            set { Set(OwinConstants.RequestMethod, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        public virtual string Scheme\n        {\n            get { return Get<string>(OwinConstants.RequestScheme); }\n            set { Set(OwinConstants.RequestScheme, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        public virtual bool IsSecure\n        {\n            get { return string.Equals(Scheme, Constants.Https, StringComparison.OrdinalIgnoreCase); }\n        }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        public virtual HostString Host\n        {\n            get { return new HostString(OwinHelpers.GetHost(this)); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Host, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        public virtual PathString PathBase\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPathBase)); }\n            set { Set(OwinConstants.RequestPathBase, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        public virtual PathString Path\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPath)); }\n            set { Set(OwinConstants.RequestPath, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        public virtual QueryString QueryString\n        {\n            get { return new QueryString(Get<string>(OwinConstants.RequestQueryString)); }\n            set { Set(OwinConstants.RequestQueryString, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        public virtual IReadableStringCollection Query\n        {\n            get { return new ReadableStringCollection(OwinHelpers.GetQuery(this)); }\n        }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        public virtual Uri Uri\n        {\n            get { return new Uri(Scheme + \"://\" + Host + PathBase + Path + QueryString); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.RequestProtocol); }\n            set { Set(OwinConstants.RequestProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.RequestHeaders); }\n        }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        public RequestCookieCollection Cookies\n        {\n            get { return new RequestCookieCollection(OwinHelpers.GetCookies(this)); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        public virtual string CacheControl\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.CacheControl); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.CacheControl, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        public virtual string MediaType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.MediaType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.MediaType, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        public virtual string Accept\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Accept); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Accept, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.RequestBody); }\n            set { Set(OwinConstants.RequestBody, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        public virtual CancellationToken CallCancelled\n        {\n            get { return Get<CancellationToken>(OwinConstants.CallCancelled); }\n            set { Set(OwinConstants.CallCancelled, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        public virtual string LocalIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalIpAddress); }\n            set { Set(OwinConstants.CommonKeys.LocalIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        public virtual int? LocalPort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(LocalPortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    LocalPortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.LocalPort);\n                }\n            }\n        }\n\n        private string LocalPortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalPort); }\n            set { Set(OwinConstants.CommonKeys.LocalPort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        public virtual string RemoteIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemoteIpAddress); }\n            set { Set(OwinConstants.CommonKeys.RemoteIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        public virtual int? RemotePort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(RemotePortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    RemotePortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.RemotePort);\n                }\n            }\n        }\n\n        private string RemotePortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemotePort); }\n            set { Set(OwinConstants.CommonKeys.RemotePort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        public virtual ClaimsPrincipal User\n        {\n            get\n            {\n                var claimsPrincipal = Get<ClaimsPrincipal>(OwinConstants.RequestUser);\n                return claimsPrincipal ?? Get<IPrincipal>(OwinConstants.Security.User) as ClaimsPrincipal;\n            }\n            set { Set(OwinConstants.RequestUser, value); }\n        }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        public async Task<IFormCollection> ReadFormAsync()\n        {\n            var form = Get<IFormCollection>(\"Microsoft.Owin.Form#collection\");\n            if (form == null)\n            {\n                string text;\n                // Don't close, it prevents re-winding.\n                using (var reader = new StreamReader(Body, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4 * 1024, leaveOpen: true))\n                {\n                    text = await reader.ReadToEndAsync();\n                }\n                form = OwinHelpers.GetForm(text);\n                Set(\"Microsoft.Owin.Form#collection\", form);\n            }\n\n            return form;\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinRequest Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinResponse : IOwinResponse\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinResponse()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Creates a new environment wrapper exposing response properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinResponse(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        public virtual int StatusCode\n        {\n            get { return Get<int>(OwinConstants.ResponseStatusCode, 200); }\n            set { Set(OwinConstants.ResponseStatusCode, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        public virtual string ReasonPhrase\n        {\n            get { return Get<string>(OwinConstants.ResponseReasonPhrase); }\n            set { Set(OwinConstants.ResponseReasonPhrase, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.ResponseProtocol); }\n            set { Set(OwinConstants.ResponseProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders); }\n        }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        public virtual ResponseCookieCollection Cookies\n        {\n            get { return new ResponseCookieCollection(Headers); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        public virtual long? ContentLength\n        {\n            get\n            {\n                long value;\n                if (long.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentLength), out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentLength,\n                        value.Value.ToString(CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.ContentLength);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        public virtual DateTimeOffset? Expires\n        {\n            get\n            {\n                DateTimeOffset value;\n                if (DateTimeOffset.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Expires),\n                    CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Expires,\n                        value.Value.ToString(Constants.HttpDateFormat, CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.Expires);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        public virtual string ETag\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ETag); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ETag, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.ResponseBody); }\n            set { Set(OwinConstants.ResponseBody, value); }\n        }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public virtual void OnSendingHeaders(Action<object> callback, object state)\n        {\n            var onSendingHeaders = Get<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);\n            if (onSendingHeaders == null)\n            {\n                throw new NotSupportedException(Resources.Exception_MissingOnSendingHeaders);\n            }\n            onSendingHeaders(callback, state);\n        }\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        public virtual void Redirect(string location)\n        {\n            StatusCode = 302;\n            OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Location, location);\n        }\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        public virtual void Write(string text)\n        {\n            Write(Encoding.UTF8.GetBytes(text));\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        public virtual void Write(byte[] data)\n        {\n            Write(data, 0, data == null ? 0 : data.Length);\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        public virtual void Write(byte[] data, int offset, int count)\n        {\n            Body.Write(data, offset, count);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text)\n        {\n            return WriteAsync(text, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text, CancellationToken token)\n        {\n            return WriteAsync(Encoding.UTF8.GetBytes(text), token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data)\n        {\n            return WriteAsync(data, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, CancellationToken token)\n        {\n            return WriteAsync(data, 0, data == null ? 0 : data.Length, token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, int offset, int count, CancellationToken token)\n        {\n            return Body.WriteAsync(data, offset, count, token);\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            return Get(key, default(T));\n        }\n\n        private T Get<T>(string key, T fallback)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : fallback;\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinResponse Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct PathString : IEquatable<PathString>\n    {\n        private static readonly Func<string, string> EscapeDataString = Uri.EscapeDataString;\n\n        /// <summary>\n        /// Represents the empty path. This field is read-only.\n        /// </summary>\n        public static readonly PathString Empty = new PathString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initialize the path string with a given value. This value must be in un-escaped format. Use\n        /// PathString.FromUriComponent(value) if you have a path value which is in an escaped format.\n        /// </summary>\n        /// <param name=\"value\">The unescaped path to be assigned to the Value property.</param>\n        public PathString(string value)\n        {\n            if (!String.IsNullOrEmpty(value) && value[0] != '/')\n            {\n                throw new ArgumentException(Resources.Exception_PathMustStartWithSlash, \"value\");\n            }\n            _value = value;\n        }\n\n        /// <summary>\n        /// The unescaped path value\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the path is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrEmpty(_value); }\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public string ToUriComponent()\n        {\n            if (HasValue)\n            {\n                if (RequiresEscaping(_value))\n                {\n                    // TODO: Measure the cost of this escaping and consider optimizing.\n                    return String.Join(\"/\", _value.Split('/').Select(EscapeDataString));\n                }\n                return _value;\n            }\n            return String.Empty;\n        }\n\n        // Very conservative, these characters do not need to be escaped in a path.\n        private static bool RequiresEscaping(string value)\n        {\n            for (int i = 0; i < value.Length; i++)\n            {\n                char c = value[i];\n                // Check conservatively for safe characters. See http://www.ietf.org/rfc/rfc3986.txt\n                bool safeChar =\n                    (('a' <= c && c <= 'z')\n                    || ('A' <= c && c <= 'Z')\n                    || ('0' <= c && c <= '9')\n                    || c == '/' || c == '-' || c == '_');\n                if (!safeChar)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a path.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped path as it appears in the URI format.</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(string uriComponent)\n        {\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(Uri.UnescapeDataString(uriComponent));\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(\"/\" + uri.GetComponents(UriComponents.Path, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                return value1.Length == value2.Length || value1[value2.Length] == '/';\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <param name=\"remaining\">Any remaining segments from this instance not included in the other instance.</param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other, out PathString remaining)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                if (value1.Length == value2.Length || value1[value2.Length] == '/')\n                {\n                    remaining = new PathString(value1.Substring(value2.Length));\n                    return true;\n                }\n            }\n            remaining = Empty;\n            return false;\n        }\n\n        /// <summary>\n        /// Adds two PathString instances into a combined PathString value.\n        /// </summary>\n        /// <returns>The combined PathString value</returns>\n        public PathString Add(PathString other)\n        {\n            return new PathString(Value + other.Value);\n        }\n\n        /// <summary>\n        /// Combines a PathString and QueryString into the joined URI formatted string value.\n        /// </summary>\n        /// <returns>The joined URI formatted string value</returns>\n        public string Add(QueryString other)\n        {\n            return ToUriComponent() + other.ToUriComponent();\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value using a specific StringComparison type\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison</param>\n        /// <param name=\"comparisonType\">The StringComparison type to use</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other, StringComparison comparisonType)\n        {\n            return string.Equals(_value, other._value, comparisonType);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"obj\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is PathString && Equals((PathString)obj, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation.\n        /// </summary>\n        /// <returns>The hash code</returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public static bool operator ==(PathString left, PathString right)\n        {\n            return left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are not equal</returns>\n        public static bool operator !=(PathString left, PathString right)\n        {\n            return !left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static PathString operator +(PathString left, PathString right)\n        {\n            return left.Add(right);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static string operator +(PathString left, QueryString right)\n        {\n            return left.Add(right);\n        }\n    }\n\n    /// <summary>\n    /// Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct QueryString : IEquatable<QueryString>\n    {\n        /// <summary>\n        /// Represents the empty query string. This field is read-only.\n        /// </summary>\n        public static readonly QueryString Empty = new QueryString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initalize the query string with a given value. This value must be in escaped and delimited format without\n        /// a leading '?' character.\n        /// </summary>\n        /// <param name=\"value\">The query string to be assigned to the Value property.</param>\n        public QueryString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Initialize a query string with a single given parameter name and value. The value is\n        /// </summary>\n        /// <param name=\"name\">The unencoded parameter name</param>\n        /// <param name=\"value\">The unencoded parameter value</param>\n        public QueryString(string name, string value)\n        {\n            _value = Uri.EscapeDataString(name) + '=' + Uri.EscapeDataString(value);\n        }\n\n        /// <summary>\n        /// The unescaped query string without the leading '?' character\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the query string is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrWhiteSpace(_value); }\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentally\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public string ToUriComponent()\n        {\n            // Escape things properly so System.Uri doesn't mis-interpret the data.\n            return HasValue ? \"?\" + _value.Replace(\"#\", \"%23\") : String.Empty;\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a query.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped query as it appears in the URI format.</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(string uriComponent)\n        {\n            if (String.IsNullOrEmpty(uriComponent))\n            {\n                return new QueryString(string.Empty);\n            }\n            if (uriComponent[0] != '?')\n            {\n                throw new ArgumentException(Resources.Exception_QueryStringMustStartWithDelimiter, \"uriComponent\");\n            }\n            return new QueryString(uriComponent.Substring(1));\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new QueryString(uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped));\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(QueryString other)\n        {\n            return string.Equals(_value, other._value);\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is QueryString && Equals((QueryString)obj);\n        }\n\n        /// <summary>\n        /// Returns the hash code for this instance.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? _value.GetHashCode() : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(QueryString left, QueryString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(QueryString left, QueryString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Accessors for query, forms, etc.\n    /// </summary>\n    partial class ReadableStringCollection : IReadableStringCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public ReadableStringCollection(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetJoinedValue(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public IList<string> GetValues(string key)\n        {\n            string[] values;\n            Store.TryGetValue(key, out values);\n            return values;\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    /// <summary>\n    /// A wrapper for the request Cookie header\n    /// </summary>\n    partial class RequestCookieCollection : IEnumerable<KeyValuePair<string, string>>\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public RequestCookieCollection(IDictionary<string, string> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string> Store { get; set; }\n\n        /// <summary>\n        /// Returns null rather than throwing KeyNotFoundException\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get\n            {\n                string value;\n                Store.TryGetValue(key, out value);\n                return value;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    internal static class Resources\n    {\n        internal const string Exception_MissingOnSendingHeaders = \"The OWIN key 'server.OnSsoendingHeaders' is not available for this request.\";\n        internal const string Exception_PathMustStartWithSlash = \"The path must start with a '/' followed by one or more characters.\";\n        internal const string Exception_QueryStringMustStartWithDelimiter = \"The query string must start with a '?' unless null or empty.\";\n    }\n\n    /// <summary>\n    /// A wrapper for the response Set-Cookie header\n    /// </summary>\n    partial class ResponseCookieCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"headers\"></param>\n        public ResponseCookieCollection(IHeaderDictionary headers)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n\n            Headers = headers;\n        }\n\n        private IHeaderDictionary Headers { get; set; }\n\n        /// <summary>\n        /// Add a new cookie and value\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        public void Append(string key, string value)\n        {\n            Headers.AppendValues(Constants.Headers.SetCookie, Uri.EscapeDataString(key) + \"=\" + Uri.EscapeDataString(value) + \"; path=/\");\n        }\n\n        /// <summary>\n        /// Add a new cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        /// <param name=\"options\"></param>\n        public void Append(string key, string value, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n            bool expiresHasValue = options.Expires.HasValue;\n\n            string setCookieValue = string.Concat(\n                Uri.EscapeDataString(key),\n                \"=\",\n                Uri.EscapeDataString(value ?? string.Empty),\n                !domainHasValue ? null : \"; domain=\",\n                !domainHasValue ? null : options.Domain,\n                !pathHasValue ? null : \"; path=\",\n                !pathHasValue ? null : options.Path,\n                !expiresHasValue ? null : \"; expires=\",\n                !expiresHasValue ? null : options.Expires.Value.ToString(\"ddd, dd-MMM-yyyy HH:mm:ss \", CultureInfo.InvariantCulture) + \"GMT\",\n                !options.Secure ? null : \"; secure\",\n                !options.HttpOnly ? null : \"; HttpOnly\");\n            Headers.AppendValues(\"Set-Cookie\", setCookieValue);\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        public void Delete(string key)\n        {\n            Func<string, bool> predicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n\n            var deleteCookies = new[] { Uri.EscapeDataString(key) + \"=; expires=Thu, 01-Jan-1970 00:00:00 GMT\" };\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues == null || existingValues.Count == 0)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, deleteCookies);\n            }\n            else\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !predicate(value)).Concat(deleteCookies).ToArray());\n            }\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"options\"></param>\n        public void Delete(string key, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n\n            Func<string, bool> rejectPredicate;\n            if (domainHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"domain=\" + options.Domain, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else if (pathHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"path=\" + options.Path, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else\n            {\n                rejectPredicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n            }\n\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues != null)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !rejectPredicate(value)).ToArray());\n            }\n\n            Append(key, string.Empty, new CookieOptions\n            {\n                Path = options.Path,\n                Domain = options.Domain,\n                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),\n            });\n        }\n    }\n\n\n    static partial class IOwinResponseExtension \n    {\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"response\">The owin response</param>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public static void OnSendingHeaders<T>(this IOwinResponse response, Action<T> callback, T state)\n        {\n            if (response == null) {\n                throw new ArgumentNullException(\"response\");\n            }\n            Action<object> innerCallback = innerState => callback((T)innerState);\n            response.OnSendingHeaders(innerCallback, state);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "src/Chapter11/MicroserivceNET.Auth/AuthorizationMiddleware.cs",
    "content": "namespace MicroserviceNET.Auth\n{\n  using System.IdentityModel.Tokens.Jwt;\n  using System.Threading.Tasks;\n  using LibOwin;\n  using Microsoft.IdentityModel.Tokens;\n\n  using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;\n\n  public class Authorization\n  {\n    public static AppFunc Middleware(AppFunc next, string requiredScope)\n    {\n      return env =>\n      {\n        var ctx = new OwinContext(env);\n        var principal = ctx.Request.User;\n        if (principal.HasClaim(\"scope\", requiredScope))\n          return next(env);\n        ctx.Response.StatusCode = 403;\n        return Task.FromResult(0);\n      };\n    }\n  }\n\n  public class IdToken\n  {\n    public static AppFunc Middleware(AppFunc next)\n    {\n      return env =>\n      {\n        var ctx = new OwinContext(env);\n        if (ctx.Request.Headers.ContainsKey(\"microservice.NET-end-user\"))\n        {\n          var tokenHandler = new JwtSecurityTokenHandler();\n          SecurityToken token;\n          var userPrincipal =\n            tokenHandler.ValidateToken(ctx.Request.Headers[\"microservice.NET-end-user\"],\n                                       new TokenValidationParameters(), out token);\n          ctx.Set(\"pos-end-user\", userPrincipal);\n        }\n        return next(env);\n      };\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter11/MicroserivceNET.Auth/BuildFuncExtensions.cs",
    "content": "namespace MicroserviceNET.Auth\n{\n  using BuildFunc = System.Action<System.Func<\n    System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>,\n    System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>>>;\n\n  public static class BuildFuncExtensions\n  {\n    public static BuildFunc UseAuthPlatform(this BuildFunc buildFunc, string requiredScope)\n    {\n      buildFunc(next => Authorization.Middleware(next, requiredScope));\n      buildFunc(next => IdToken.Middleware(next));\n      return buildFunc;\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter11/MicroserivceNET.Auth/MicroserivceNET.Auth.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>662415b4-3486-4b64-b1f9-718b9ff0879d</ProjectGuid>\n    <RootNamespace>MicroserivceNET.Auth</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter11/MicroserivceNET.Auth/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n\n  \"dependencies\": {\n    \"NETStandard.Library\": \"1.5.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"System.IdentityModel.Tokens.Jwt\": \"5.0.0-rc2-305061149\",\n    \"System.Security.Principal\": \"4.0.1\",\n    \"System.Security.Claims\": \"4.0.1\",\n    \"System.Globalization.Extensions\": \"4.0.1\"\n  },\n\n  \"frameworks\": {\n    \"netstandard1.5\": {\n      \"imports\": \"dnxcore50\"\n    }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"MicroserivceNET.Auth\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Logging/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Logging/Application_Packages/LibOwin.cs",
    "content": "﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.\n// Copyright (c) Damian Hickey. All rights reserved. See License.txt in the project root for license information.\n\n// https://github.com/damianh/LibOwin\n// Modifying this file may result in difficulties when upgrading the package.\n// All types are internal. Add a LIBOWIN_PUBLIC compilation symbol to make them public.\n\nnamespace LibOwin.Infrastructure\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Linq;\n\n    internal static partial class Constants\n    {\n        internal const string Https = \"HTTPS\";\n\n        internal const string HttpDateFormat = \"r\";\n\n        internal static partial class Headers\n        {\n            internal const string ContentType = \"Content-Type\";\n            internal const string CacheControl = \"Cache-Control\";\n            internal const string MediaType = \"Media-Type\";\n            internal const string Accept = \"Accept\";\n            internal const string Host = \"Host\";\n            internal const string ETag = \"ETag\";\n            internal const string Location = \"Location\";\n            internal const string ContentLength = \"Content-Length\";\n            internal const string SetCookie = \"Set-Cookie\";\n            internal const string Expires = \"Expires\";\n        }\n    }\n\n    internal struct HeaderSegment : IEquatable<HeaderSegment>\n    {\n        private readonly StringSegment _formatting;\n        private readonly StringSegment _data;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public HeaderSegment(StringSegment formatting, StringSegment data)\n        {\n            _formatting = formatting;\n            _data = data;\n        }\n\n        public StringSegment Formatting\n        {\n            get { return _formatting; }\n        }\n\n        public StringSegment Data\n        {\n            get { return _data; }\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegment other)\n        {\n            return _formatting.Equals(other._formatting) && _data.Equals(other._data);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegment && Equals((HeaderSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return (_formatting.GetHashCode() * 397) ^ _data.GetHashCode();\n            }\n        }\n\n        public static bool operator ==(HeaderSegment left, HeaderSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegment left, HeaderSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n    }\n\n    internal struct HeaderSegmentCollection : IEnumerable<HeaderSegment>, IEquatable<HeaderSegmentCollection>\n    {\n        private readonly string[] _headers;\n\n        public HeaderSegmentCollection(string[] headers)\n        {\n            _headers = headers;\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegmentCollection other)\n        {\n            return Equals(_headers, other._headers);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegmentCollection && Equals((HeaderSegmentCollection)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return (_headers != null ? _headers.GetHashCode() : 0);\n        }\n\n        public static bool operator ==(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public Enumerator GetEnumerator()\n        {\n            return new Enumerator(_headers);\n        }\n\n        IEnumerator<HeaderSegment> IEnumerable<HeaderSegment>.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        internal struct Enumerator : IEnumerator<HeaderSegment>\n        {\n            private readonly string[] _headers;\n            private int _index;\n\n            private string _header;\n            private int _headerLength;\n            private int _offset;\n\n            private int _leadingStart;\n            private int _leadingEnd;\n            private int _valueStart;\n            private int _valueEnd;\n            private int _trailingStart;\n\n            private Mode _mode;\n\n            private static readonly string[] NoHeaders = new string[0];\n\n            public Enumerator(string[] headers)\n            {\n                _headers = headers ?? NoHeaders;\n                _header = string.Empty;\n                _headerLength = -1;\n                _index = -1;\n                _offset = -1;\n                _leadingStart = -1;\n                _leadingEnd = -1;\n                _valueStart = -1;\n                _valueEnd = -1;\n                _trailingStart = -1;\n                _mode = Mode.Leading;\n            }\n\n            private enum Mode\n            {\n                Leading,\n                Value,\n                ValueQuoted,\n                Trailing,\n                Produce,\n            }\n\n            private enum Attr\n            {\n                Value,\n                Quote,\n                Delimiter,\n                Whitespace\n            }\n\n            public HeaderSegment Current\n            {\n                get\n                {\n                    return new HeaderSegment(\n                        new StringSegment(_header, _leadingStart, _leadingEnd - _leadingStart),\n                        new StringSegment(_header, _valueStart, _valueEnd - _valueStart));\n                }\n            }\n\n            object IEnumerator.Current\n            {\n                get { return Current; }\n            }\n\n            public void Dispose()\n            {\n            }\n\n            public bool MoveNext()\n            {\n                while (true)\n                {\n                    if (_mode == Mode.Produce)\n                    {\n                        _leadingStart = _trailingStart;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        if (_offset == _headerLength &&\n                            _leadingStart != -1 &&\n                            _leadingStart != _offset)\n                        {\n                            // Also produce trailing whitespace\n                            _leadingEnd = _offset;\n                            return true;\n                        }\n                        _mode = Mode.Leading;\n                    }\n\n                    // if end of a string\n                    if (_offset == _headerLength)\n                    {\n                        ++_index;\n                        _offset = -1;\n                        _leadingStart = 0;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        // if that was the last string\n                        if (_index == _headers.Length)\n                        {\n                            // no more move nexts\n                            return false;\n                        }\n\n                        // grab the next string\n                        _header = _headers[_index] ?? string.Empty;\n                        _headerLength = _header.Length;\n                    }\n                    while (true)\n                    {\n                        ++_offset;\n                        char ch = _offset == _headerLength ? (char)0 : _header[_offset];\n                        // todo - array of attrs\n                        Attr attr = char.IsWhiteSpace(ch) ? Attr.Whitespace : ch == '\\\"' ? Attr.Quote : (ch == ',' || ch == (char)0) ? Attr.Delimiter : Attr.Value;\n\n                        switch (_mode)\n                        {\n                            case Mode.Leading:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _leadingEnd = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Value:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Delimiter:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Value:\n                                        // more\n                                        break;\n                                    case Attr.Whitespace:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Trailing;\n                                        break;\n                                }\n                                break;\n                            case Mode.ValueQuoted:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Delimiter:\n                                        if (ch == (char)0)\n                                        {\n                                            _valueEnd = _offset;\n                                            _trailingStart = _offset;\n                                            _mode = Mode.Produce;\n                                        }\n                                        break;\n                                    case Attr.Value:\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Trailing:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                        }\n                        if (_mode == Mode.Produce)\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n\n            public void Reset()\n            {\n                _index = 0;\n                _offset = 0;\n                _leadingStart = 0;\n                _leadingEnd = 0;\n                _valueStart = 0;\n                _valueEnd = 0;\n            }\n        }\n    }\n\n    internal struct StringSegment : IEquatable<StringSegment>\n    {\n        private readonly string _buffer;\n        private readonly int _offset;\n        private readonly int _count;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public StringSegment(string buffer, int offset, int count)\n        {\n            _buffer = buffer;\n            _offset = offset;\n            _count = count;\n        }\n\n        public string Buffer\n        {\n            get { return _buffer; }\n        }\n\n        public int Offset\n        {\n            get { return _offset; }\n        }\n\n        public int Count\n        {\n            get { return _count; }\n        }\n\n        public string Value\n        {\n            get { return _offset == -1 ? null : _buffer.Substring(_offset, _count); }\n        }\n\n        public bool HasValue\n        {\n            get { return _offset != -1 && _count != 0 && _buffer != null; }\n        }\n\n        #region Equality members\n\n        public bool Equals(StringSegment other)\n        {\n            return string.Equals(_buffer, other._buffer) && _offset == other._offset && _count == other._count;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is StringSegment && Equals((StringSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hashCode = (_buffer != null ? _buffer.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ _offset;\n                hashCode = (hashCode * 397) ^ _count;\n                return hashCode;\n            }\n        }\n\n        public static bool operator ==(StringSegment left, StringSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(StringSegment left, StringSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public bool StartsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool EndsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset + _count - textLength, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool Equals(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count != textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public string Substring(int offset, int length)\n        {\n            return _buffer.Substring(_offset + offset, length);\n        }\n\n        public StringSegment Subsegment(int offset, int length)\n        {\n            return new StringSegment(_buffer, _offset + offset, length);\n        }\n\n        public override string ToString()\n        {\n            return Value ?? string.Empty;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AddCookieCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, string>)state;\n            if (!dictionary.ContainsKey(name))\n            {\n                dictionary.Add(name, value);\n            }\n        };\n\n        private static readonly char[] SemicolonAndComma = new[] { ';', ',' };\n\n        internal static IDictionary<string, string> GetCookies(IOwinRequest request)\n        {\n            var cookies = request.Get<IDictionary<string, string>>(\"Microsoft.Owin.Cookies#dictionary\");\n            if (cookies == null)\n            {\n                cookies = new Dictionary<string, string>(StringComparer.Ordinal);\n                request.Set(\"Microsoft.Owin.Cookies#dictionary\", cookies);\n            }\n\n            string text = GetHeader(request.Headers, \"Cookie\");\n            if (request.Get<string>(\"Microsoft.Owin.Cookies#text\") != text)\n            {\n                cookies.Clear();\n                ParseDelimited(text, SemicolonAndComma, AddCookieCallback, cookies);\n                request.Set(\"Microsoft.Owin.Cookies#text\", text);\n            }\n            return cookies;\n        }\n\n        internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)\n        {\n            int textLength = text.Length;\n            int equalIndex = text.IndexOf('=');\n            if (equalIndex == -1)\n            {\n                equalIndex = textLength;\n            }\n            int scanIndex = 0;\n            while (scanIndex < textLength)\n            {\n                int delimiterIndex = text.IndexOfAny(delimiters, scanIndex);\n                if (delimiterIndex == -1)\n                {\n                    delimiterIndex = textLength;\n                }\n                if (equalIndex < delimiterIndex)\n                {\n                    while (scanIndex != equalIndex && char.IsWhiteSpace(text[scanIndex]))\n                    {\n                        ++scanIndex;\n                    }\n                    string name = text.Substring(scanIndex, equalIndex - scanIndex);\n                    string value = text.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);\n                    callback(\n                        Uri.UnescapeDataString(name.Replace('+', ' ')),\n                        Uri.UnescapeDataString(value.Replace('+', ' ')),\n                        state);\n                    equalIndex = text.IndexOf('=', delimiterIndex);\n                    if (equalIndex == -1)\n                    {\n                        equalIndex = textLength;\n                    }\n                }\n                scanIndex = delimiterIndex + 1;\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        public static string GetHeader(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        public static IEnumerable<string> GetHeaderSplit(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : GetHeaderSplitImplementation(values);\n        }\n\n        private static IEnumerable<string> GetHeaderSplitImplementation(string[] values)\n        {\n            foreach (var segment in new HeaderSegmentCollection(values))\n            {\n                if (segment.Data.HasValue)\n                {\n                    yield return DeQuote(segment.Data.Value);\n                }\n            }\n        }\n\n        public static string[] GetHeaderUnmodified(IDictionary<string, string[]> headers, string key)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            string[] values;\n            return headers.TryGetValue(key, out values) ? values : null;\n        }\n\n        public static void SetHeader(IDictionary<string, string[]> headers, string key, string value)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { value };\n            }\n        }\n\n        public static void SetHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        // Quote items that contain comas and are not already quoted.\n        private static string QuoteIfNeeded(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Contains(','))\n            {\n                if (value[0] != '\"' || value[value.Length - 1] != '\"')\n                {\n                    value = '\"' + value + '\"';\n                }\n            }\n\n            return value;\n        }\n\n        private static string DeQuote(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Length > 1 && value[0] == '\"' && value[value.Length - 1] == '\"')\n            {\n                value = value.Substring(1, value.Length - 2);\n            }\n\n            return value;\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = values;\n            }\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, IEnumerable<string> values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            headers[key] = values.ToArray();\n        }\n\n        public static void AppendHeader(IDictionary<string, string[]> headers, string key, string values)\n        {\n            if (string.IsNullOrWhiteSpace(values))\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeader(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + values };\n            }\n        }\n\n        public static void AppendHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeaderJoined(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        public static void AppendHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string[] existing = GetHeaderUnmodified(headers, key);\n            if (existing == null)\n            {\n                SetHeaderUnmodified(headers, key, values);\n            }\n            else\n            {\n                SetHeaderUnmodified(headers, key, existing.Concat(values));\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AppendItemCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, List<String>>)state;\n\n            List<string> existing;\n            if (!dictionary.TryGetValue(name, out existing))\n            {\n                dictionary.Add(name, new List<string>(1) { value });\n            }\n            else\n            {\n                existing.Add(value);\n            }\n        };\n\n        private static readonly char[] AmpersandAndSemicolon = new[] { '&', ';' };\n\n        internal static IDictionary<string, string[]> GetQuery(IOwinRequest request)\n        {\n            var query = request.Get<IDictionary<string, string[]>>(\"Microsoft.Owin.Query#dictionary\");\n            if (query == null)\n            {\n                query = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n                request.Set(\"Microsoft.Owin.Query#dictionary\", query);\n            }\n\n            string text = request.QueryString.Value;\n            if (request.Get<string>(\"Microsoft.Owin.Query#text\") != text)\n            {\n                query.Clear();\n                var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n                ParseDelimited(text, AmpersandAndSemicolon, AppendItemCallback, accumulator);\n                foreach (var kv in accumulator)\n                {\n                    query.Add(kv.Key, kv.Value.ToArray());\n                }\n                request.Set(\"Microsoft.Owin.Query#text\", text);\n            }\n            return query;\n        }\n\n        internal static IFormCollection GetForm(string text)\n        {\n            IDictionary<string, string[]> form = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n            ParseDelimited(text, new[] { '&' }, AppendItemCallback, accumulator);\n            foreach (var kv in accumulator)\n            {\n                form.Add(kv.Key, kv.Value.ToArray());\n            }\n            return new FormCollection(form);\n        }\n\n        internal static string GetJoinedValue(IDictionary<string, string[]> store, string key)\n        {\n            string[] values = GetUnmodifiedValues(store, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        internal static string[] GetUnmodifiedValues(IDictionary<string, string[]> store, string key)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n            string[] values;\n            return store.TryGetValue(key, out values) ? values : null;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        internal static string GetHost(IOwinRequest request)\n        {\n            IHeaderDictionary headers = request.Headers;\n\n            string host = GetHeader(headers, \"Host\");\n            if (!string.IsNullOrWhiteSpace(host))\n            {\n                return host;\n            }\n\n            string localIpAddress = request.LocalIpAddress ?? \"localhost\";\n            var localPort = request.Get<string>(OwinConstants.CommonKeys.LocalPort);\n            return string.IsNullOrWhiteSpace(localPort) ? localIpAddress : (localIpAddress + \":\" + localPort);\n        }\n    }\n}\n\nnamespace LibOwin\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Globalization;\n    using System.IO;\n    using System.Linq;\n    using System.Security.Claims;\n    using System.Security.Principal;\n    using System.Text;\n    using System.Threading;\n    using System.Threading.Tasks;\n    using LibOwin.Infrastructure;\n\n    #if LIBOWIN_PUBLIC\n\n    public partial class CookieOptions { }\n    public partial class FormCollection { }\n    public partial class HeaderDictionary { }\n    public partial struct HostString { }\n    public partial interface IFormCollection { }\n    public partial interface IHeaderDictionary { }\n    public partial interface IOwinContext { }\n    public partial interface IOwinRequest { }\n    public partial interface IOwinResponse { }\n    public partial interface IReadableStringCollection { }\n    public partial class OwinContext { }\n    public partial class OwinRequest { }\n    public partial class OwinResponse { }\n    public partial struct PathString { }\n    public partial struct QueryString { }\n    public partial class ReadableStringCollection { }\n    public partial class RequestCookieCollection { }\n    public partial class ResponseCookieCollection { }\n    public partial class IOwinResponseExtension { }\n\n    #endif\n\n    /// <summary>\n    /// Options used to create a new cookie.\n    /// </summary>\n    partial class CookieOptions\n    {\n        /// <summary>\n        /// Creates a default cookie with a path of '/'.\n        /// </summary>\n        public CookieOptions()\n        {\n            Path = \"/\";\n        }\n\n        /// <summary>\n        /// Gets or sets the domain to associate the cookie with.\n        /// </summary>\n        /// <returns>The domain to associate the cookie with.</returns>\n        public string Domain { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cookie path.\n        /// </summary>\n        /// <returns>The cookie path.</returns>\n        public string Path { get; set; }\n\n        /// <summary>\n        /// Gets or sets the expiration date and time for the cookie.\n        /// </summary>\n        /// <returns>The expiration date and time for the cookie.</returns>\n        public DateTime? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether to transmit the cookie using Secure Sockets Layer (SSL)—that is, over HTTPS only.\n        /// </summary>\n        /// <returns>true to transmit the cookie only over an SSL connection (HTTPS); otherwise, false.</returns>\n        public bool Secure { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether a cookie is accessible by client-side script.\n        /// </summary>\n        /// <returns>true if a cookie is accessible by client-side script; otherwise, false.</returns>\n        public bool HttpOnly { get; set; }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial class FormCollection : ReadableStringCollection, IFormCollection\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.FormCollection\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The store for the form.</param>\n        public FormCollection(IDictionary<string, string[]> store)\n            : base(store)\n        {}\n    }\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial class HeaderDictionary : IHeaderDictionary\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The underlying data store.</param>\n        public HeaderDictionary(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Gets an <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public ICollection<string> Keys\n        {\n            get { return Store.Keys; }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        public ICollection<string[]> Values\n        {\n            get { return Store.Values; }\n        }\n\n        /// <summary>\n        /// Gets the number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>The number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public int Count\n        {\n            get { return Store.Count; }\n        }\n\n        /// <summary>\n        /// Gets a value that indicates whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode.\n        /// </summary>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode; otherwise, false.</returns>\n        public bool IsReadOnly\n        {\n            get { return Store.IsReadOnly; }\n        }\n\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n            set { Set(key, value); }\n        }\n\n        /// <summary>\n        /// Throws KeyNotFoundException if the key is not present.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns></returns>\n        string[] IDictionary<string, string[]>.this[string key]\n        {\n            get { return Store[key]; }\n            set { Store[key] = value; }\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetHeader(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection without modification, or null if the key is not present.</returns>\n        public IList<string> GetValues(string key)\n        {\n            return OwinHelpers.GetHeaderUnmodified(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        public IList<string> GetCommaSeparatedValues(string key)\n        {\n            IEnumerable<string> values = OwinHelpers.GetHeaderSplit(Store, key);\n            return values == null ? null : values.ToList();\n        }\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Append(string key, string value)\n        {\n            OwinHelpers.AppendHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Set(string key, string value)\n        {\n            OwinHelpers.SetHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Adds the given header and values to the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header values.</param>\n        public void Add(string key, string[] value)\n        {\n            Store.Add(key, value);\n        }\n\n        /// <summary>\n        /// Determines whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key.\n        /// </summary>\n        /// <param name=\"key\">The key.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key; otherwise, false.</returns>\n        public bool ContainsKey(string key)\n        {\n            return Store.ContainsKey(key);\n        }\n\n        /// <summary>\n        /// Removes the given header from the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(string key)\n        {\n            return Store.Remove(key);\n        }\n\n        /// <summary>\n        /// Retrieves a value from the dictionary.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The value.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains the key; otherwise, false.</returns>\n        public bool TryGetValue(string key, out string[] value)\n        {\n            return Store.TryGetValue(key, out value);\n        }\n\n        /// <summary>\n        /// Adds a new list of items to the collection.\n        /// </summary>\n        /// <param name=\"item\">The item to add.</param>\n        public void Add(KeyValuePair<string, string[]> item)\n        {\n            Store.Add(item);\n        }\n\n        /// <summary>\n        /// Clears the entire list of objects.\n        /// </summary>\n        public void Clear()\n        {\n            Store.Clear();\n        }\n\n        /// <summary>\n        /// Returns a value indicating whether the specified object occurs within this collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object occurs within this collection; otherwise, false.</returns>\n        public bool Contains(KeyValuePair<string, string[]> item)\n        {\n            return Store.Contains(item);\n        }\n\n        /// <summary>\n        /// Copies the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> elements to a one-dimensional Array instance at the specified index.\n        /// </summary>\n        /// <param name=\"array\">The one-dimensional Array that is the destination of the specified objects copied from the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</param>\n        /// <param name=\"arrayIndex\">The zero-based index in <paramref name=\"array\" /> at which copying begins.</param>\n        public void CopyTo(KeyValuePair<string, string[]>[] array, int arrayIndex)\n        {\n            Store.CopyTo(array, arrayIndex);\n        }\n\n        /// <summary>\n        /// Removes the given item from the the collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(KeyValuePair<string, string[]> item)\n        {\n            return Store.Remove(item);\n        }\n    }\n\n    /// <summary>\n    /// Represents the host portion of a Uri can be used to construct Uri's properly formatted and encoded for use in\n    /// HTTP headers.\n    /// </summary>\n    partial struct HostString : IEquatable<HostString>\n    {\n        private readonly string _value;\n\n        /// <summary>\n        /// Creates a new HostString without modification. The value should be Unicode rather than punycode, and may have a port.\n        /// IPv4 and IPv6 addresses are also allowed, and also may have ports.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        public HostString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Returns the original value from the constructor.\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// Returns the value as normalized by ToUriComponent().\n        /// </summary>\n        /// <returns></returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Returns the value properly formatted and encoded for use in a URI in a HTTP header.\n        /// Any Unicode is converted to punycode. IPv6 addresses will have brackets added if they are missing.\n        /// </summary>\n        /// <returns></returns>\n        public string ToUriComponent()\n        {\n            int index;\n            if (string.IsNullOrEmpty(_value))\n            {\n                return string.Empty;\n            }\n            else if (_value.IndexOf('[') >= 0)\n            {\n                // IPv6 in brackets [::1], maybe with port\n                return _value;\n            }\n            else if ((index = _value.IndexOf(':')) >= 0\n                && index < _value.Length - 1\n                && _value.IndexOf(':', index + 1) >= 0)\n            {\n                // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                return \"[\" + _value + \"]\";\n            }\n            else if (index >= 0)\n            {\n                // Has a port\n                string port = _value.Substring(index);\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value, 0, index) + port;\n            }\n            else\n            {\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value);\n            }\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the given uri component.\n        /// Any punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uriComponent\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(string uriComponent)\n        {\n            if (!string.IsNullOrEmpty(uriComponent))\n            {\n                int index;\n                if (uriComponent.IndexOf('[') >= 0)\n                {\n                    // IPv6 in brackets [::1], maybe with port\n                }\n                else if ((index = uriComponent.IndexOf(':')) >= 0\n                    && index < uriComponent.Length - 1\n                    && uriComponent.IndexOf(':', index + 1) >= 0)\n                {\n                    // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                }\n                else if (uriComponent.IndexOf(\"xn--\", StringComparison.Ordinal) >= 0)\n                {\n                    // Contains punycode\n                    if (index >= 0)\n                    {\n                        // Has a port\n                        string port = uriComponent.Substring(index);\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent, 0, index) + port;\n                    }\n                    else\n                    {\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent);\n                    }\n                }\n            }\n            return new HostString(uriComponent);\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the host and port of the give Uri instance.\n        /// Punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uri\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new HostString(uri.GetComponents(\n                UriComponents.NormalizedHost | // Always convert punycode to Unicode.\n                UriComponents.HostAndPort, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Compares the equality of the Value property, ignoring case.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(HostString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares against the given object only if it is a HostString.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is HostString && Equals((HostString)obj);\n        }\n\n        /// <summary>\n        /// Gets a hash code for the value.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(HostString left, HostString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(HostString left, HostString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial interface IFormCollection : IReadableStringCollection\n    {}\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, string[]>\n    {\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        new string this[string key] { get; set; }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        IList<string> GetCommaSeparatedValues(string key);\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Append(string key, string value);\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendCommaSeparatedValues(string key, params string[] values);\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Set(string key, string value);\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetCommaSeparatedValues(string key, params string[] values);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinContext\n    {\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        IOwinRequest Request { get; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        IOwinResponse Response { get; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        TextWriter TraceOutput { get; set; }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinContext Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinRequest\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        string Method { get; set; }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        string Scheme { get; set; }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        bool IsSecure { get; }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        HostString Host { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        PathString PathBase { get; set; }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        PathString Path { get; set; }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        QueryString QueryString { get; set; }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        IReadableStringCollection Query { get; }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        Uri Uri { get; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        RequestCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        string CacheControl { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        string MediaType { get; set; }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        string Accept { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        CancellationToken CallCancelled { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        string LocalIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        int? LocalPort { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        string RemoteIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        int? RemotePort { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        ClaimsPrincipal User { get; set; }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        Task<IFormCollection> ReadFormAsync();\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinRequest Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinResponse\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        int StatusCode { get; set; }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        string ReasonPhrase { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        ResponseCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        long? ContentLength { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        DateTimeOffset? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        string ETag { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        void OnSendingHeaders(Action<object> callback, object state);\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        void Redirect(string location);\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        void Write(string text);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        void Write(byte[] data);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        void Write(byte[] data, int offset, int count);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, int offset, int count, CancellationToken token);\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinResponse Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// Accessors for headers, query, forms, etc.\n    /// </summary>\n    partial interface IReadableStringCollection : IEnumerable<KeyValuePair<string, string[]>>\n    {\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string this[string key] { get; }\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string Get(string key);\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        IList<string> GetValues(string key);\n\n        // Raw\n    }\n\n    internal static class OwinConstants\n    {\n        #region OWIN v1.0.0 - 3.2.1. Request Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string RequestScheme = \"owin.RequestScheme\";\n        public const string RequestMethod = \"owin.RequestMethod\";\n        public const string RequestPathBase = \"owin.RequestPathBase\";\n        public const string RequestPath = \"owin.RequestPath\";\n        public const string RequestQueryString = \"owin.RequestQueryString\";\n        public const string RequestProtocol = \"owin.RequestProtocol\";\n        public const string RequestHeaders = \"owin.RequestHeaders\";\n        public const string RequestBody = \"owin.RequestBody\";\n        public const string RequestUser = \"owin.RequestUser\"; //owin 1.0.1\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.2. Response Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string ResponseStatusCode = \"owin.ResponseStatusCode\";\n        public const string ResponseReasonPhrase = \"owin.ResponseReasonPhrase\";\n        public const string ResponseProtocol = \"owin.ResponseProtocol\";\n        public const string ResponseHeaders = \"owin.ResponseHeaders\";\n        public const string ResponseBody = \"owin.ResponseBody\";\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.3. Other Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string CallCancelled = \"owin.CallCancelled\";\n\n        public const string OwinVersion = \"owin.Version\";\n\n        #endregion\n\n        #region OWIN Keys for IAppBuilder.Properties\n\n        internal static class Builder\n        {\n            public const string AddSignatureConversion = \"builder.AddSignatureConversion\";\n            public const string DefaultApp = \"builder.DefaultApp\";\n        }\n\n        #endregion\n\n        #region OWIN Key Guidelines and Common Keys - 6. Common keys\n\n        // http://owin.org/spec/CommonKeys.html\n\n        internal static class CommonKeys\n        {\n            public const string ClientCertificate = \"ssl.ClientCertificate\";\n            public const string RemoteIpAddress = \"server.RemoteIpAddress\";\n            public const string RemotePort = \"server.RemotePort\";\n            public const string LocalIpAddress = \"server.LocalIpAddress\";\n            public const string LocalPort = \"server.LocalPort\";\n            public const string IsLocal = \"server.IsLocal\";\n            public const string TraceOutput = \"host.TraceOutput\";\n            public const string Addresses = \"host.Addresses\";\n            public const string AppName = \"host.AppName\";\n            public const string Capabilities = \"server.Capabilities\";\n            public const string OnSendingHeaders = \"server.OnSendingHeaders\";\n            public const string OnAppDisposing = \"host.OnAppDisposing\";\n            public const string Scheme = \"scheme\";\n            public const string Host = \"host\";\n            public const string Port = \"port\";\n            public const string Path = \"path\";\n        }\n\n        #endregion\n\n        #region SendFiles v0.3.0\n\n        // http://owin.org/extensions/owin-SendFile-Extension-v0.3.0.htm\n\n        internal static class SendFiles\n        {\n            // 3.1. Startup\n\n            public const string Version = \"sendfile.Version\";\n            public const string Support = \"sendfile.Support\";\n            public const string Concurrency = \"sendfile.Concurrency\";\n\n            // 3.2. Per Request\n\n            public const string SendAsync = \"sendfile.SendAsync\";\n        }\n\n        #endregion\n\n        #region Opaque v0.3.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class OpaqueConstants\n        {\n            // 3.1. Startup\n            public const string Version = \"opaque.Version\";\n\n            // 3.2. Per Request\n            public const string Upgrade = \"opaque.Upgrade\";\n\n            // 5. Consumption\n            public const string Stream = \"opaque.Stream\";\n            // public const string Version = \"opaque.Version\"; // redundant, declared above\n            public const string CallCancelled = \"opaque.CallCancelled\";\n        }\n\n        #endregion\n\n        #region WebSocket v0.4.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class WebSocket\n        {\n            // 3.1. Startup\n            public const string Version = \"websocket.Version\";\n\n            // 3.2. Per Request\n            public const string Accept = \"websocket.Accept\";\n\n            // 4. Accept\n            public const string SubProtocol = \"websocket.SubProtocol\";\n\n            // 5. Consumption\n            public const string SendAsync = \"websocket.SendAsync\";\n            public const string ReceiveAsync = \"websocket.ReceiveAsync\";\n            public const string CloseAsync = \"websocket.CloseAsync\";\n            // public const string Version = \"websocket.Version\"; // redundant, declared above\n            public const string CallCancelled = \"websocket.CallCancelled\";\n            public const string ClientCloseStatus = \"websocket.ClientCloseStatus\";\n            public const string ClientCloseDescription = \"websocket.ClientCloseDescription\";\n        }\n\n        #endregion\n\n        #region Security v0.1.0\n\n        // http://owin.org/extensions/owin-Security-Extension-v0.1.0.htm\n\n        internal static class Security\n        {\n            // 3.2. Per Request\n\n            public const string User = \"server.User\";\n\n            public const string Authenticate = \"security.Authenticate\";\n\n            // 3.3. Response\n\n            public const string SignIn = \"security.SignIn\";\n\n            public const string SignOut = \"security.SignOut\";\n\n            public const string SignOutProperties = \"security.SignOutProperties\";\n\n            public const string Challenge = \"security.Challenge\";\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinContext : IOwinContext\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinContext()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Create a new wrapper.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinContext(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        public virtual IOwinRequest Request { get; private set; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        public virtual IOwinResponse Response { get; private set; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        public virtual TextWriter TraceOutput\n        {\n            get { return Get<TextWriter>(OwinConstants.CommonKeys.TraceOutput); }\n            set { Set<TextWriter>(OwinConstants.CommonKeys.TraceOutput, value); }\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinContext Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinRequest : IOwinRequest\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinRequest()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Create a new environment wrapper exposing request properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinRequest(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        public virtual string Method\n        {\n            get { return Get<string>(OwinConstants.RequestMethod); }\n            set { Set(OwinConstants.RequestMethod, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        public virtual string Scheme\n        {\n            get { return Get<string>(OwinConstants.RequestScheme); }\n            set { Set(OwinConstants.RequestScheme, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        public virtual bool IsSecure\n        {\n            get { return string.Equals(Scheme, Constants.Https, StringComparison.OrdinalIgnoreCase); }\n        }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        public virtual HostString Host\n        {\n            get { return new HostString(OwinHelpers.GetHost(this)); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Host, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        public virtual PathString PathBase\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPathBase)); }\n            set { Set(OwinConstants.RequestPathBase, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        public virtual PathString Path\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPath)); }\n            set { Set(OwinConstants.RequestPath, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        public virtual QueryString QueryString\n        {\n            get { return new QueryString(Get<string>(OwinConstants.RequestQueryString)); }\n            set { Set(OwinConstants.RequestQueryString, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        public virtual IReadableStringCollection Query\n        {\n            get { return new ReadableStringCollection(OwinHelpers.GetQuery(this)); }\n        }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        public virtual Uri Uri\n        {\n            get { return new Uri(Scheme + \"://\" + Host + PathBase + Path + QueryString); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.RequestProtocol); }\n            set { Set(OwinConstants.RequestProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.RequestHeaders); }\n        }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        public RequestCookieCollection Cookies\n        {\n            get { return new RequestCookieCollection(OwinHelpers.GetCookies(this)); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        public virtual string CacheControl\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.CacheControl); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.CacheControl, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        public virtual string MediaType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.MediaType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.MediaType, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        public virtual string Accept\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Accept); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Accept, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.RequestBody); }\n            set { Set(OwinConstants.RequestBody, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        public virtual CancellationToken CallCancelled\n        {\n            get { return Get<CancellationToken>(OwinConstants.CallCancelled); }\n            set { Set(OwinConstants.CallCancelled, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        public virtual string LocalIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalIpAddress); }\n            set { Set(OwinConstants.CommonKeys.LocalIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        public virtual int? LocalPort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(LocalPortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    LocalPortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.LocalPort);\n                }\n            }\n        }\n\n        private string LocalPortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalPort); }\n            set { Set(OwinConstants.CommonKeys.LocalPort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        public virtual string RemoteIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemoteIpAddress); }\n            set { Set(OwinConstants.CommonKeys.RemoteIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        public virtual int? RemotePort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(RemotePortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    RemotePortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.RemotePort);\n                }\n            }\n        }\n\n        private string RemotePortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemotePort); }\n            set { Set(OwinConstants.CommonKeys.RemotePort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        public virtual ClaimsPrincipal User\n        {\n            get\n            {\n                var claimsPrincipal = Get<ClaimsPrincipal>(OwinConstants.RequestUser);\n                return claimsPrincipal ?? Get<IPrincipal>(OwinConstants.Security.User) as ClaimsPrincipal;\n            }\n            set { Set(OwinConstants.RequestUser, value); }\n        }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        public async Task<IFormCollection> ReadFormAsync()\n        {\n            var form = Get<IFormCollection>(\"Microsoft.Owin.Form#collection\");\n            if (form == null)\n            {\n                string text;\n                // Don't close, it prevents re-winding.\n                using (var reader = new StreamReader(Body, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4 * 1024, leaveOpen: true))\n                {\n                    text = await reader.ReadToEndAsync();\n                }\n                form = OwinHelpers.GetForm(text);\n                Set(\"Microsoft.Owin.Form#collection\", form);\n            }\n\n            return form;\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinRequest Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinResponse : IOwinResponse\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinResponse()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Creates a new environment wrapper exposing response properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinResponse(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        public virtual int StatusCode\n        {\n            get { return Get<int>(OwinConstants.ResponseStatusCode, 200); }\n            set { Set(OwinConstants.ResponseStatusCode, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        public virtual string ReasonPhrase\n        {\n            get { return Get<string>(OwinConstants.ResponseReasonPhrase); }\n            set { Set(OwinConstants.ResponseReasonPhrase, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.ResponseProtocol); }\n            set { Set(OwinConstants.ResponseProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders); }\n        }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        public virtual ResponseCookieCollection Cookies\n        {\n            get { return new ResponseCookieCollection(Headers); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        public virtual long? ContentLength\n        {\n            get\n            {\n                long value;\n                if (long.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentLength), out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentLength,\n                        value.Value.ToString(CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.ContentLength);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        public virtual DateTimeOffset? Expires\n        {\n            get\n            {\n                DateTimeOffset value;\n                if (DateTimeOffset.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Expires),\n                    CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Expires,\n                        value.Value.ToString(Constants.HttpDateFormat, CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.Expires);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        public virtual string ETag\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ETag); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ETag, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.ResponseBody); }\n            set { Set(OwinConstants.ResponseBody, value); }\n        }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public virtual void OnSendingHeaders(Action<object> callback, object state)\n        {\n            var onSendingHeaders = Get<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);\n            if (onSendingHeaders == null)\n            {\n                throw new NotSupportedException(Resources.Exception_MissingOnSendingHeaders);\n            }\n            onSendingHeaders(callback, state);\n        }\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        public virtual void Redirect(string location)\n        {\n            StatusCode = 302;\n            OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Location, location);\n        }\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        public virtual void Write(string text)\n        {\n            Write(Encoding.UTF8.GetBytes(text));\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        public virtual void Write(byte[] data)\n        {\n            Write(data, 0, data == null ? 0 : data.Length);\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        public virtual void Write(byte[] data, int offset, int count)\n        {\n            Body.Write(data, offset, count);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text)\n        {\n            return WriteAsync(text, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text, CancellationToken token)\n        {\n            return WriteAsync(Encoding.UTF8.GetBytes(text), token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data)\n        {\n            return WriteAsync(data, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, CancellationToken token)\n        {\n            return WriteAsync(data, 0, data == null ? 0 : data.Length, token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, int offset, int count, CancellationToken token)\n        {\n            return Body.WriteAsync(data, offset, count, token);\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            return Get(key, default(T));\n        }\n\n        private T Get<T>(string key, T fallback)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : fallback;\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinResponse Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct PathString : IEquatable<PathString>\n    {\n        private static readonly Func<string, string> EscapeDataString = Uri.EscapeDataString;\n\n        /// <summary>\n        /// Represents the empty path. This field is read-only.\n        /// </summary>\n        public static readonly PathString Empty = new PathString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initialize the path string with a given value. This value must be in un-escaped format. Use\n        /// PathString.FromUriComponent(value) if you have a path value which is in an escaped format.\n        /// </summary>\n        /// <param name=\"value\">The unescaped path to be assigned to the Value property.</param>\n        public PathString(string value)\n        {\n            if (!String.IsNullOrEmpty(value) && value[0] != '/')\n            {\n                throw new ArgumentException(Resources.Exception_PathMustStartWithSlash, \"value\");\n            }\n            _value = value;\n        }\n\n        /// <summary>\n        /// The unescaped path value\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the path is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrEmpty(_value); }\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public string ToUriComponent()\n        {\n            if (HasValue)\n            {\n                if (RequiresEscaping(_value))\n                {\n                    // TODO: Measure the cost of this escaping and consider optimizing.\n                    return String.Join(\"/\", _value.Split('/').Select(EscapeDataString));\n                }\n                return _value;\n            }\n            return String.Empty;\n        }\n\n        // Very conservative, these characters do not need to be escaped in a path.\n        private static bool RequiresEscaping(string value)\n        {\n            for (int i = 0; i < value.Length; i++)\n            {\n                char c = value[i];\n                // Check conservatively for safe characters. See http://www.ietf.org/rfc/rfc3986.txt\n                bool safeChar =\n                    (('a' <= c && c <= 'z')\n                    || ('A' <= c && c <= 'Z')\n                    || ('0' <= c && c <= '9')\n                    || c == '/' || c == '-' || c == '_');\n                if (!safeChar)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a path.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped path as it appears in the URI format.</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(string uriComponent)\n        {\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(Uri.UnescapeDataString(uriComponent));\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(\"/\" + uri.GetComponents(UriComponents.Path, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                return value1.Length == value2.Length || value1[value2.Length] == '/';\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <param name=\"remaining\">Any remaining segments from this instance not included in the other instance.</param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other, out PathString remaining)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                if (value1.Length == value2.Length || value1[value2.Length] == '/')\n                {\n                    remaining = new PathString(value1.Substring(value2.Length));\n                    return true;\n                }\n            }\n            remaining = Empty;\n            return false;\n        }\n\n        /// <summary>\n        /// Adds two PathString instances into a combined PathString value.\n        /// </summary>\n        /// <returns>The combined PathString value</returns>\n        public PathString Add(PathString other)\n        {\n            return new PathString(Value + other.Value);\n        }\n\n        /// <summary>\n        /// Combines a PathString and QueryString into the joined URI formatted string value.\n        /// </summary>\n        /// <returns>The joined URI formatted string value</returns>\n        public string Add(QueryString other)\n        {\n            return ToUriComponent() + other.ToUriComponent();\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value using a specific StringComparison type\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison</param>\n        /// <param name=\"comparisonType\">The StringComparison type to use</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other, StringComparison comparisonType)\n        {\n            return string.Equals(_value, other._value, comparisonType);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"obj\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is PathString && Equals((PathString)obj, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation.\n        /// </summary>\n        /// <returns>The hash code</returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public static bool operator ==(PathString left, PathString right)\n        {\n            return left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are not equal</returns>\n        public static bool operator !=(PathString left, PathString right)\n        {\n            return !left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static PathString operator +(PathString left, PathString right)\n        {\n            return left.Add(right);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static string operator +(PathString left, QueryString right)\n        {\n            return left.Add(right);\n        }\n    }\n\n    /// <summary>\n    /// Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct QueryString : IEquatable<QueryString>\n    {\n        /// <summary>\n        /// Represents the empty query string. This field is read-only.\n        /// </summary>\n        public static readonly QueryString Empty = new QueryString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initalize the query string with a given value. This value must be in escaped and delimited format without\n        /// a leading '?' character.\n        /// </summary>\n        /// <param name=\"value\">The query string to be assigned to the Value property.</param>\n        public QueryString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Initialize a query string with a single given parameter name and value. The value is\n        /// </summary>\n        /// <param name=\"name\">The unencoded parameter name</param>\n        /// <param name=\"value\">The unencoded parameter value</param>\n        public QueryString(string name, string value)\n        {\n            _value = Uri.EscapeDataString(name) + '=' + Uri.EscapeDataString(value);\n        }\n\n        /// <summary>\n        /// The unescaped query string without the leading '?' character\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the query string is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrWhiteSpace(_value); }\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentally\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public string ToUriComponent()\n        {\n            // Escape things properly so System.Uri doesn't mis-interpret the data.\n            return HasValue ? \"?\" + _value.Replace(\"#\", \"%23\") : String.Empty;\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a query.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped query as it appears in the URI format.</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(string uriComponent)\n        {\n            if (String.IsNullOrEmpty(uriComponent))\n            {\n                return new QueryString(string.Empty);\n            }\n            if (uriComponent[0] != '?')\n            {\n                throw new ArgumentException(Resources.Exception_QueryStringMustStartWithDelimiter, \"uriComponent\");\n            }\n            return new QueryString(uriComponent.Substring(1));\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new QueryString(uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped));\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(QueryString other)\n        {\n            return string.Equals(_value, other._value);\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is QueryString && Equals((QueryString)obj);\n        }\n\n        /// <summary>\n        /// Returns the hash code for this instance.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? _value.GetHashCode() : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(QueryString left, QueryString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(QueryString left, QueryString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Accessors for query, forms, etc.\n    /// </summary>\n    partial class ReadableStringCollection : IReadableStringCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public ReadableStringCollection(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetJoinedValue(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public IList<string> GetValues(string key)\n        {\n            string[] values;\n            Store.TryGetValue(key, out values);\n            return values;\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    /// <summary>\n    /// A wrapper for the request Cookie header\n    /// </summary>\n    partial class RequestCookieCollection : IEnumerable<KeyValuePair<string, string>>\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public RequestCookieCollection(IDictionary<string, string> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string> Store { get; set; }\n\n        /// <summary>\n        /// Returns null rather than throwing KeyNotFoundException\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get\n            {\n                string value;\n                Store.TryGetValue(key, out value);\n                return value;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    internal static class Resources\n    {\n        internal const string Exception_MissingOnSendingHeaders = \"The OWIN key 'server.OnSsoendingHeaders' is not available for this request.\";\n        internal const string Exception_PathMustStartWithSlash = \"The path must start with a '/' followed by one or more characters.\";\n        internal const string Exception_QueryStringMustStartWithDelimiter = \"The query string must start with a '?' unless null or empty.\";\n    }\n\n    /// <summary>\n    /// A wrapper for the response Set-Cookie header\n    /// </summary>\n    partial class ResponseCookieCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"headers\"></param>\n        public ResponseCookieCollection(IHeaderDictionary headers)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n\n            Headers = headers;\n        }\n\n        private IHeaderDictionary Headers { get; set; }\n\n        /// <summary>\n        /// Add a new cookie and value\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        public void Append(string key, string value)\n        {\n            Headers.AppendValues(Constants.Headers.SetCookie, Uri.EscapeDataString(key) + \"=\" + Uri.EscapeDataString(value) + \"; path=/\");\n        }\n\n        /// <summary>\n        /// Add a new cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        /// <param name=\"options\"></param>\n        public void Append(string key, string value, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n            bool expiresHasValue = options.Expires.HasValue;\n\n            string setCookieValue = string.Concat(\n                Uri.EscapeDataString(key),\n                \"=\",\n                Uri.EscapeDataString(value ?? string.Empty),\n                !domainHasValue ? null : \"; domain=\",\n                !domainHasValue ? null : options.Domain,\n                !pathHasValue ? null : \"; path=\",\n                !pathHasValue ? null : options.Path,\n                !expiresHasValue ? null : \"; expires=\",\n                !expiresHasValue ? null : options.Expires.Value.ToString(\"ddd, dd-MMM-yyyy HH:mm:ss \", CultureInfo.InvariantCulture) + \"GMT\",\n                !options.Secure ? null : \"; secure\",\n                !options.HttpOnly ? null : \"; HttpOnly\");\n            Headers.AppendValues(\"Set-Cookie\", setCookieValue);\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        public void Delete(string key)\n        {\n            Func<string, bool> predicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n\n            var deleteCookies = new[] { Uri.EscapeDataString(key) + \"=; expires=Thu, 01-Jan-1970 00:00:00 GMT\" };\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues == null || existingValues.Count == 0)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, deleteCookies);\n            }\n            else\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !predicate(value)).Concat(deleteCookies).ToArray());\n            }\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"options\"></param>\n        public void Delete(string key, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n\n            Func<string, bool> rejectPredicate;\n            if (domainHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"domain=\" + options.Domain, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else if (pathHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"path=\" + options.Path, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else\n            {\n                rejectPredicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n            }\n\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues != null)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !rejectPredicate(value)).ToArray());\n            }\n\n            Append(key, string.Empty, new CookieOptions\n            {\n                Path = options.Path,\n                Domain = options.Domain,\n                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),\n            });\n        }\n    }\n\n\n    static partial class IOwinResponseExtension \n    {\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"response\">The owin response</param>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public static void OnSendingHeaders<T>(this IOwinResponse response, Action<T> callback, T state)\n        {\n            if (response == null) {\n                throw new ArgumentNullException(\"response\");\n            }\n            Action<object> innerCallback = innerState => callback((T)innerState);\n            response.OnSendingHeaders(innerCallback, state);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Logging/BuildFuncExtensions.cs",
    "content": "﻿namespace MicroserviceNET.Logging\n{\n  using System;\n  using System.Threading.Tasks;\n  using Serilog;\n\n   using BuildFunc = System.Action<System.Func<\n    System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>,\n    System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>>>;\n\n  public static class BuildFuncExtensions\n  {\n    public static BuildFunc UseMonitoringAndLogging(\n      this BuildFunc buildFunc,\n      ILogger log,\n      Func<Task<bool>> healthCheck)\n    {\n      buildFunc(next => GlobalErrorLogging.Middleware(next, log));\n      buildFunc(next => CorrelationToken.Middleware(next));\n      buildFunc(next => RequestLogging.Middleware(next, log));\n      buildFunc(next => PerformanceLogging.Middleware(next, log));\n      buildFunc(next => new MonitoringMiddleware(next, healthCheck).Invoke);\n      return buildFunc;\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Logging/LoggingMiddleware.cs",
    "content": "﻿namespace MicroserviceNET.Logging\n{\n  using System;\n  using System.Diagnostics;\n  using LibOwin;\n  using Serilog;\n  using Serilog.Context;\n\n  using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;\n\n  public class RequestLogging\n  {\n    public static AppFunc Middleware(AppFunc next, ILogger log)\n    {\n      return async env =>\n      {\n        var owinContext = new OwinContext(env);\n        log.Information(\"Incoming request: {@Method}, {@Path}, {@Headers}\",\n                        owinContext.Request.Method,\n                        owinContext.Request.Path,\n                        owinContext.Request.Headers);\n        await next(env).ConfigureAwait(false);\n        log.Information(\"Outgoing response: {@StatusCode}, {@Headers}\",\n                        owinContext.Response.StatusCode,\n                        owinContext.Response.Headers);\n      };\n    }\n  }\n\n  public class PerformanceLogging\n  {\n    public static AppFunc Middleware(AppFunc next, ILogger log)\n    {\n      return async env =>\n      {\n        var stopWatch = new Stopwatch();\n        stopWatch.Start();\n        await next(env).ConfigureAwait(false);\n        stopWatch.Stop();\n        var owinContext = new OwinContext(env);\n        log.Information(\"Request: {@Method} {@Path} executed in {RequestTime:000} ms\",\n                        owinContext.Request.Method, owinContext.Request.Path,\n                        stopWatch.ElapsedMilliseconds);\n      };\n    }\n  }\n\n  public class CorrelationToken\n  {\n    public static AppFunc Middleware(AppFunc next)\n    {\n      return async env =>\n      {\n        Guid correlationToken;\n        var owinContext = new OwinContext(env);\n        if (!(owinContext.Request.Headers[\"Correlation-Token\"] != null\n              && Guid.TryParse(owinContext.Request.Headers[\"Correlation-Token\"], out correlationToken)))\n          correlationToken = Guid.NewGuid();\n\n        owinContext.Set(\"correlationToken\", correlationToken.ToString());\n        using (LogContext.PushProperty(\"CorrelationToken\", correlationToken))\n          await next(env).ConfigureAwait(false);\n      };\n    }\n  }\n\n  public class GlobalErrorLogging\n  {\n    public static AppFunc Middleware(AppFunc next, ILogger log)\n    {\n      return async env =>\n      {\n        try\n        {\n          await next(env).ConfigureAwait(false);\n        }\n        catch (Exception ex)\n        {\n          log.Error(ex, \"Unhandled exception\");\n        }\n      };\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Logging/MicroserviceNET.Logging.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>f73df2ab-708b-4916-ac28-e95117466511</ProjectGuid>\n    <RootNamespace>MicroserviceNET.Logging</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Logging/MonitoringMiddleware.cs",
    "content": "﻿namespace MicroserviceNET.Logging\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Threading.Tasks;\n  using LibOwin;\n\n  using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;\n\n  public class MonitoringMiddleware\n  {\n    private readonly AppFunc next;\n    private readonly Func<Task<bool>> healthCheck;\n\n    private static readonly PathString monitorPath = new PathString(\"/_monitor\");\n    private static readonly PathString monitorShallowPath = new PathString(\"/_monitor/shallow\");\n    private static readonly PathString monitorDeepPath = new PathString(\"/_monitor/deep\");\n\n    public MonitoringMiddleware(AppFunc next, Func<Task<bool>> healthCheck)\n    {\n      this.next = next;\n      this.healthCheck = healthCheck;\n    }\n\n    public Task Invoke(IDictionary<string, object> env)\n    {\n      var context = new OwinContext(env);\n      if (context.Request.Path.StartsWithSegments(monitorPath))\n        return HandleMonitorEndpoint(context);\n      else\n        return this.next(env);\n    }\n\n    private Task HandleMonitorEndpoint(OwinContext context)\n    {\n      if (context.Request.Path.StartsWithSegments(monitorShallowPath))\n        return ShallowEndpoint(context);\n      else if (context.Request.Path.StartsWithSegments(monitorDeepPath))\n        return DeepEndpoint(context);\n      return Task.FromResult(0);\n    }\n\n    private async Task DeepEndpoint(OwinContext context)\n    {\n      if (await this.healthCheck().ConfigureAwait(false))\n        context.Response.StatusCode = 204;\n      else\n        context.Response.StatusCode = 503;\n    }\n\n    private Task ShallowEndpoint(OwinContext context)\n    {\n      context.Response.StatusCode = 204;\n      return Task.FromResult(0);\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Logging/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n\n  \"dependencies\": {\n    \"NETStandard.Library\": \"1.5.0\",\n    \"Serilog\":  \"2.0.0-rc-600\",\n    \"System.Security.Principal\": \"4.0.1\",\n    \"System.Security.Claims\": \"4.0.1\",\n    \"System.Globalization.Extensions\": \"4.0.1\"\n  },\n\n  \"frameworks\": {\n    \"netstandard1.5\": {\n      \"imports\": \"dnxcore50\",\n      \"dependencies\": {\n      }\n    }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"MicroserviceNET.Logging\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Platform/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Platform/Application_Packages/LibOwin.cs",
    "content": "﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.\n// Copyright (c) Damian Hickey. All rights reserved. See License.txt in the project root for license information.\n\n// https://github.com/damianh/LibOwin\n// Modifying this file may result in difficulties when upgrading the package.\n// All types are internal. Add a LIBOWIN_PUBLIC compilation symbol to make them public.\n\nnamespace LibOwin.Infrastructure\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Linq;\n\n    internal static partial class Constants\n    {\n        internal const string Https = \"HTTPS\";\n\n        internal const string HttpDateFormat = \"r\";\n\n        internal static partial class Headers\n        {\n            internal const string ContentType = \"Content-Type\";\n            internal const string CacheControl = \"Cache-Control\";\n            internal const string MediaType = \"Media-Type\";\n            internal const string Accept = \"Accept\";\n            internal const string Host = \"Host\";\n            internal const string ETag = \"ETag\";\n            internal const string Location = \"Location\";\n            internal const string ContentLength = \"Content-Length\";\n            internal const string SetCookie = \"Set-Cookie\";\n            internal const string Expires = \"Expires\";\n        }\n    }\n\n    internal struct HeaderSegment : IEquatable<HeaderSegment>\n    {\n        private readonly StringSegment _formatting;\n        private readonly StringSegment _data;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public HeaderSegment(StringSegment formatting, StringSegment data)\n        {\n            _formatting = formatting;\n            _data = data;\n        }\n\n        public StringSegment Formatting\n        {\n            get { return _formatting; }\n        }\n\n        public StringSegment Data\n        {\n            get { return _data; }\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegment other)\n        {\n            return _formatting.Equals(other._formatting) && _data.Equals(other._data);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegment && Equals((HeaderSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return (_formatting.GetHashCode() * 397) ^ _data.GetHashCode();\n            }\n        }\n\n        public static bool operator ==(HeaderSegment left, HeaderSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegment left, HeaderSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n    }\n\n    internal struct HeaderSegmentCollection : IEnumerable<HeaderSegment>, IEquatable<HeaderSegmentCollection>\n    {\n        private readonly string[] _headers;\n\n        public HeaderSegmentCollection(string[] headers)\n        {\n            _headers = headers;\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegmentCollection other)\n        {\n            return Equals(_headers, other._headers);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegmentCollection && Equals((HeaderSegmentCollection)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return (_headers != null ? _headers.GetHashCode() : 0);\n        }\n\n        public static bool operator ==(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public Enumerator GetEnumerator()\n        {\n            return new Enumerator(_headers);\n        }\n\n        IEnumerator<HeaderSegment> IEnumerable<HeaderSegment>.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        internal struct Enumerator : IEnumerator<HeaderSegment>\n        {\n            private readonly string[] _headers;\n            private int _index;\n\n            private string _header;\n            private int _headerLength;\n            private int _offset;\n\n            private int _leadingStart;\n            private int _leadingEnd;\n            private int _valueStart;\n            private int _valueEnd;\n            private int _trailingStart;\n\n            private Mode _mode;\n\n            private static readonly string[] NoHeaders = new string[0];\n\n            public Enumerator(string[] headers)\n            {\n                _headers = headers ?? NoHeaders;\n                _header = string.Empty;\n                _headerLength = -1;\n                _index = -1;\n                _offset = -1;\n                _leadingStart = -1;\n                _leadingEnd = -1;\n                _valueStart = -1;\n                _valueEnd = -1;\n                _trailingStart = -1;\n                _mode = Mode.Leading;\n            }\n\n            private enum Mode\n            {\n                Leading,\n                Value,\n                ValueQuoted,\n                Trailing,\n                Produce,\n            }\n\n            private enum Attr\n            {\n                Value,\n                Quote,\n                Delimiter,\n                Whitespace\n            }\n\n            public HeaderSegment Current\n            {\n                get\n                {\n                    return new HeaderSegment(\n                        new StringSegment(_header, _leadingStart, _leadingEnd - _leadingStart),\n                        new StringSegment(_header, _valueStart, _valueEnd - _valueStart));\n                }\n            }\n\n            object IEnumerator.Current\n            {\n                get { return Current; }\n            }\n\n            public void Dispose()\n            {\n            }\n\n            public bool MoveNext()\n            {\n                while (true)\n                {\n                    if (_mode == Mode.Produce)\n                    {\n                        _leadingStart = _trailingStart;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        if (_offset == _headerLength &&\n                            _leadingStart != -1 &&\n                            _leadingStart != _offset)\n                        {\n                            // Also produce trailing whitespace\n                            _leadingEnd = _offset;\n                            return true;\n                        }\n                        _mode = Mode.Leading;\n                    }\n\n                    // if end of a string\n                    if (_offset == _headerLength)\n                    {\n                        ++_index;\n                        _offset = -1;\n                        _leadingStart = 0;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        // if that was the last string\n                        if (_index == _headers.Length)\n                        {\n                            // no more move nexts\n                            return false;\n                        }\n\n                        // grab the next string\n                        _header = _headers[_index] ?? string.Empty;\n                        _headerLength = _header.Length;\n                    }\n                    while (true)\n                    {\n                        ++_offset;\n                        char ch = _offset == _headerLength ? (char)0 : _header[_offset];\n                        // todo - array of attrs\n                        Attr attr = char.IsWhiteSpace(ch) ? Attr.Whitespace : ch == '\\\"' ? Attr.Quote : (ch == ',' || ch == (char)0) ? Attr.Delimiter : Attr.Value;\n\n                        switch (_mode)\n                        {\n                            case Mode.Leading:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _leadingEnd = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Value:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Delimiter:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Value:\n                                        // more\n                                        break;\n                                    case Attr.Whitespace:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Trailing;\n                                        break;\n                                }\n                                break;\n                            case Mode.ValueQuoted:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Delimiter:\n                                        if (ch == (char)0)\n                                        {\n                                            _valueEnd = _offset;\n                                            _trailingStart = _offset;\n                                            _mode = Mode.Produce;\n                                        }\n                                        break;\n                                    case Attr.Value:\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Trailing:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                        }\n                        if (_mode == Mode.Produce)\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n\n            public void Reset()\n            {\n                _index = 0;\n                _offset = 0;\n                _leadingStart = 0;\n                _leadingEnd = 0;\n                _valueStart = 0;\n                _valueEnd = 0;\n            }\n        }\n    }\n\n    internal struct StringSegment : IEquatable<StringSegment>\n    {\n        private readonly string _buffer;\n        private readonly int _offset;\n        private readonly int _count;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public StringSegment(string buffer, int offset, int count)\n        {\n            _buffer = buffer;\n            _offset = offset;\n            _count = count;\n        }\n\n        public string Buffer\n        {\n            get { return _buffer; }\n        }\n\n        public int Offset\n        {\n            get { return _offset; }\n        }\n\n        public int Count\n        {\n            get { return _count; }\n        }\n\n        public string Value\n        {\n            get { return _offset == -1 ? null : _buffer.Substring(_offset, _count); }\n        }\n\n        public bool HasValue\n        {\n            get { return _offset != -1 && _count != 0 && _buffer != null; }\n        }\n\n        #region Equality members\n\n        public bool Equals(StringSegment other)\n        {\n            return string.Equals(_buffer, other._buffer) && _offset == other._offset && _count == other._count;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is StringSegment && Equals((StringSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hashCode = (_buffer != null ? _buffer.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ _offset;\n                hashCode = (hashCode * 397) ^ _count;\n                return hashCode;\n            }\n        }\n\n        public static bool operator ==(StringSegment left, StringSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(StringSegment left, StringSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public bool StartsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool EndsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset + _count - textLength, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool Equals(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count != textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public string Substring(int offset, int length)\n        {\n            return _buffer.Substring(_offset + offset, length);\n        }\n\n        public StringSegment Subsegment(int offset, int length)\n        {\n            return new StringSegment(_buffer, _offset + offset, length);\n        }\n\n        public override string ToString()\n        {\n            return Value ?? string.Empty;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AddCookieCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, string>)state;\n            if (!dictionary.ContainsKey(name))\n            {\n                dictionary.Add(name, value);\n            }\n        };\n\n        private static readonly char[] SemicolonAndComma = new[] { ';', ',' };\n\n        internal static IDictionary<string, string> GetCookies(IOwinRequest request)\n        {\n            var cookies = request.Get<IDictionary<string, string>>(\"Microsoft.Owin.Cookies#dictionary\");\n            if (cookies == null)\n            {\n                cookies = new Dictionary<string, string>(StringComparer.Ordinal);\n                request.Set(\"Microsoft.Owin.Cookies#dictionary\", cookies);\n            }\n\n            string text = GetHeader(request.Headers, \"Cookie\");\n            if (request.Get<string>(\"Microsoft.Owin.Cookies#text\") != text)\n            {\n                cookies.Clear();\n                ParseDelimited(text, SemicolonAndComma, AddCookieCallback, cookies);\n                request.Set(\"Microsoft.Owin.Cookies#text\", text);\n            }\n            return cookies;\n        }\n\n        internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)\n        {\n            int textLength = text.Length;\n            int equalIndex = text.IndexOf('=');\n            if (equalIndex == -1)\n            {\n                equalIndex = textLength;\n            }\n            int scanIndex = 0;\n            while (scanIndex < textLength)\n            {\n                int delimiterIndex = text.IndexOfAny(delimiters, scanIndex);\n                if (delimiterIndex == -1)\n                {\n                    delimiterIndex = textLength;\n                }\n                if (equalIndex < delimiterIndex)\n                {\n                    while (scanIndex != equalIndex && char.IsWhiteSpace(text[scanIndex]))\n                    {\n                        ++scanIndex;\n                    }\n                    string name = text.Substring(scanIndex, equalIndex - scanIndex);\n                    string value = text.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);\n                    callback(\n                        Uri.UnescapeDataString(name.Replace('+', ' ')),\n                        Uri.UnescapeDataString(value.Replace('+', ' ')),\n                        state);\n                    equalIndex = text.IndexOf('=', delimiterIndex);\n                    if (equalIndex == -1)\n                    {\n                        equalIndex = textLength;\n                    }\n                }\n                scanIndex = delimiterIndex + 1;\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        public static string GetHeader(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        public static IEnumerable<string> GetHeaderSplit(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : GetHeaderSplitImplementation(values);\n        }\n\n        private static IEnumerable<string> GetHeaderSplitImplementation(string[] values)\n        {\n            foreach (var segment in new HeaderSegmentCollection(values))\n            {\n                if (segment.Data.HasValue)\n                {\n                    yield return DeQuote(segment.Data.Value);\n                }\n            }\n        }\n\n        public static string[] GetHeaderUnmodified(IDictionary<string, string[]> headers, string key)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            string[] values;\n            return headers.TryGetValue(key, out values) ? values : null;\n        }\n\n        public static void SetHeader(IDictionary<string, string[]> headers, string key, string value)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { value };\n            }\n        }\n\n        public static void SetHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        // Quote items that contain comas and are not already quoted.\n        private static string QuoteIfNeeded(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Contains(','))\n            {\n                if (value[0] != '\"' || value[value.Length - 1] != '\"')\n                {\n                    value = '\"' + value + '\"';\n                }\n            }\n\n            return value;\n        }\n\n        private static string DeQuote(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Length > 1 && value[0] == '\"' && value[value.Length - 1] == '\"')\n            {\n                value = value.Substring(1, value.Length - 2);\n            }\n\n            return value;\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = values;\n            }\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, IEnumerable<string> values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            headers[key] = values.ToArray();\n        }\n\n        public static void AppendHeader(IDictionary<string, string[]> headers, string key, string values)\n        {\n            if (string.IsNullOrWhiteSpace(values))\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeader(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + values };\n            }\n        }\n\n        public static void AppendHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeaderJoined(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        public static void AppendHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string[] existing = GetHeaderUnmodified(headers, key);\n            if (existing == null)\n            {\n                SetHeaderUnmodified(headers, key, values);\n            }\n            else\n            {\n                SetHeaderUnmodified(headers, key, existing.Concat(values));\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AppendItemCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, List<String>>)state;\n\n            List<string> existing;\n            if (!dictionary.TryGetValue(name, out existing))\n            {\n                dictionary.Add(name, new List<string>(1) { value });\n            }\n            else\n            {\n                existing.Add(value);\n            }\n        };\n\n        private static readonly char[] AmpersandAndSemicolon = new[] { '&', ';' };\n\n        internal static IDictionary<string, string[]> GetQuery(IOwinRequest request)\n        {\n            var query = request.Get<IDictionary<string, string[]>>(\"Microsoft.Owin.Query#dictionary\");\n            if (query == null)\n            {\n                query = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n                request.Set(\"Microsoft.Owin.Query#dictionary\", query);\n            }\n\n            string text = request.QueryString.Value;\n            if (request.Get<string>(\"Microsoft.Owin.Query#text\") != text)\n            {\n                query.Clear();\n                var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n                ParseDelimited(text, AmpersandAndSemicolon, AppendItemCallback, accumulator);\n                foreach (var kv in accumulator)\n                {\n                    query.Add(kv.Key, kv.Value.ToArray());\n                }\n                request.Set(\"Microsoft.Owin.Query#text\", text);\n            }\n            return query;\n        }\n\n        internal static IFormCollection GetForm(string text)\n        {\n            IDictionary<string, string[]> form = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n            ParseDelimited(text, new[] { '&' }, AppendItemCallback, accumulator);\n            foreach (var kv in accumulator)\n            {\n                form.Add(kv.Key, kv.Value.ToArray());\n            }\n            return new FormCollection(form);\n        }\n\n        internal static string GetJoinedValue(IDictionary<string, string[]> store, string key)\n        {\n            string[] values = GetUnmodifiedValues(store, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        internal static string[] GetUnmodifiedValues(IDictionary<string, string[]> store, string key)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n            string[] values;\n            return store.TryGetValue(key, out values) ? values : null;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        internal static string GetHost(IOwinRequest request)\n        {\n            IHeaderDictionary headers = request.Headers;\n\n            string host = GetHeader(headers, \"Host\");\n            if (!string.IsNullOrWhiteSpace(host))\n            {\n                return host;\n            }\n\n            string localIpAddress = request.LocalIpAddress ?? \"localhost\";\n            var localPort = request.Get<string>(OwinConstants.CommonKeys.LocalPort);\n            return string.IsNullOrWhiteSpace(localPort) ? localIpAddress : (localIpAddress + \":\" + localPort);\n        }\n    }\n}\n\nnamespace LibOwin\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Globalization;\n    using System.IO;\n    using System.Linq;\n    using System.Security.Claims;\n    using System.Security.Principal;\n    using System.Text;\n    using System.Threading;\n    using System.Threading.Tasks;\n    using LibOwin.Infrastructure;\n\n    #if LIBOWIN_PUBLIC\n\n    public partial class CookieOptions { }\n    public partial class FormCollection { }\n    public partial class HeaderDictionary { }\n    public partial struct HostString { }\n    public partial interface IFormCollection { }\n    public partial interface IHeaderDictionary { }\n    public partial interface IOwinContext { }\n    public partial interface IOwinRequest { }\n    public partial interface IOwinResponse { }\n    public partial interface IReadableStringCollection { }\n    public partial class OwinContext { }\n    public partial class OwinRequest { }\n    public partial class OwinResponse { }\n    public partial struct PathString { }\n    public partial struct QueryString { }\n    public partial class ReadableStringCollection { }\n    public partial class RequestCookieCollection { }\n    public partial class ResponseCookieCollection { }\n    public partial class IOwinResponseExtension { }\n\n    #endif\n\n    /// <summary>\n    /// Options used to create a new cookie.\n    /// </summary>\n    partial class CookieOptions\n    {\n        /// <summary>\n        /// Creates a default cookie with a path of '/'.\n        /// </summary>\n        public CookieOptions()\n        {\n            Path = \"/\";\n        }\n\n        /// <summary>\n        /// Gets or sets the domain to associate the cookie with.\n        /// </summary>\n        /// <returns>The domain to associate the cookie with.</returns>\n        public string Domain { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cookie path.\n        /// </summary>\n        /// <returns>The cookie path.</returns>\n        public string Path { get; set; }\n\n        /// <summary>\n        /// Gets or sets the expiration date and time for the cookie.\n        /// </summary>\n        /// <returns>The expiration date and time for the cookie.</returns>\n        public DateTime? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether to transmit the cookie using Secure Sockets Layer (SSL)—that is, over HTTPS only.\n        /// </summary>\n        /// <returns>true to transmit the cookie only over an SSL connection (HTTPS); otherwise, false.</returns>\n        public bool Secure { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether a cookie is accessible by client-side script.\n        /// </summary>\n        /// <returns>true if a cookie is accessible by client-side script; otherwise, false.</returns>\n        public bool HttpOnly { get; set; }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial class FormCollection : ReadableStringCollection, IFormCollection\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.FormCollection\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The store for the form.</param>\n        public FormCollection(IDictionary<string, string[]> store)\n            : base(store)\n        {}\n    }\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial class HeaderDictionary : IHeaderDictionary\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The underlying data store.</param>\n        public HeaderDictionary(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Gets an <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public ICollection<string> Keys\n        {\n            get { return Store.Keys; }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        public ICollection<string[]> Values\n        {\n            get { return Store.Values; }\n        }\n\n        /// <summary>\n        /// Gets the number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>The number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public int Count\n        {\n            get { return Store.Count; }\n        }\n\n        /// <summary>\n        /// Gets a value that indicates whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode.\n        /// </summary>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode; otherwise, false.</returns>\n        public bool IsReadOnly\n        {\n            get { return Store.IsReadOnly; }\n        }\n\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n            set { Set(key, value); }\n        }\n\n        /// <summary>\n        /// Throws KeyNotFoundException if the key is not present.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns></returns>\n        string[] IDictionary<string, string[]>.this[string key]\n        {\n            get { return Store[key]; }\n            set { Store[key] = value; }\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetHeader(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection without modification, or null if the key is not present.</returns>\n        public IList<string> GetValues(string key)\n        {\n            return OwinHelpers.GetHeaderUnmodified(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        public IList<string> GetCommaSeparatedValues(string key)\n        {\n            IEnumerable<string> values = OwinHelpers.GetHeaderSplit(Store, key);\n            return values == null ? null : values.ToList();\n        }\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Append(string key, string value)\n        {\n            OwinHelpers.AppendHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Set(string key, string value)\n        {\n            OwinHelpers.SetHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Adds the given header and values to the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header values.</param>\n        public void Add(string key, string[] value)\n        {\n            Store.Add(key, value);\n        }\n\n        /// <summary>\n        /// Determines whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key.\n        /// </summary>\n        /// <param name=\"key\">The key.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key; otherwise, false.</returns>\n        public bool ContainsKey(string key)\n        {\n            return Store.ContainsKey(key);\n        }\n\n        /// <summary>\n        /// Removes the given header from the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(string key)\n        {\n            return Store.Remove(key);\n        }\n\n        /// <summary>\n        /// Retrieves a value from the dictionary.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The value.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains the key; otherwise, false.</returns>\n        public bool TryGetValue(string key, out string[] value)\n        {\n            return Store.TryGetValue(key, out value);\n        }\n\n        /// <summary>\n        /// Adds a new list of items to the collection.\n        /// </summary>\n        /// <param name=\"item\">The item to add.</param>\n        public void Add(KeyValuePair<string, string[]> item)\n        {\n            Store.Add(item);\n        }\n\n        /// <summary>\n        /// Clears the entire list of objects.\n        /// </summary>\n        public void Clear()\n        {\n            Store.Clear();\n        }\n\n        /// <summary>\n        /// Returns a value indicating whether the specified object occurs within this collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object occurs within this collection; otherwise, false.</returns>\n        public bool Contains(KeyValuePair<string, string[]> item)\n        {\n            return Store.Contains(item);\n        }\n\n        /// <summary>\n        /// Copies the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> elements to a one-dimensional Array instance at the specified index.\n        /// </summary>\n        /// <param name=\"array\">The one-dimensional Array that is the destination of the specified objects copied from the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</param>\n        /// <param name=\"arrayIndex\">The zero-based index in <paramref name=\"array\" /> at which copying begins.</param>\n        public void CopyTo(KeyValuePair<string, string[]>[] array, int arrayIndex)\n        {\n            Store.CopyTo(array, arrayIndex);\n        }\n\n        /// <summary>\n        /// Removes the given item from the the collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(KeyValuePair<string, string[]> item)\n        {\n            return Store.Remove(item);\n        }\n    }\n\n    /// <summary>\n    /// Represents the host portion of a Uri can be used to construct Uri's properly formatted and encoded for use in\n    /// HTTP headers.\n    /// </summary>\n    partial struct HostString : IEquatable<HostString>\n    {\n        private readonly string _value;\n\n        /// <summary>\n        /// Creates a new HostString without modification. The value should be Unicode rather than punycode, and may have a port.\n        /// IPv4 and IPv6 addresses are also allowed, and also may have ports.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        public HostString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Returns the original value from the constructor.\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// Returns the value as normalized by ToUriComponent().\n        /// </summary>\n        /// <returns></returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Returns the value properly formatted and encoded for use in a URI in a HTTP header.\n        /// Any Unicode is converted to punycode. IPv6 addresses will have brackets added if they are missing.\n        /// </summary>\n        /// <returns></returns>\n        public string ToUriComponent()\n        {\n            int index;\n            if (string.IsNullOrEmpty(_value))\n            {\n                return string.Empty;\n            }\n            else if (_value.IndexOf('[') >= 0)\n            {\n                // IPv6 in brackets [::1], maybe with port\n                return _value;\n            }\n            else if ((index = _value.IndexOf(':')) >= 0\n                && index < _value.Length - 1\n                && _value.IndexOf(':', index + 1) >= 0)\n            {\n                // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                return \"[\" + _value + \"]\";\n            }\n            else if (index >= 0)\n            {\n                // Has a port\n                string port = _value.Substring(index);\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value, 0, index) + port;\n            }\n            else\n            {\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value);\n            }\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the given uri component.\n        /// Any punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uriComponent\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(string uriComponent)\n        {\n            if (!string.IsNullOrEmpty(uriComponent))\n            {\n                int index;\n                if (uriComponent.IndexOf('[') >= 0)\n                {\n                    // IPv6 in brackets [::1], maybe with port\n                }\n                else if ((index = uriComponent.IndexOf(':')) >= 0\n                    && index < uriComponent.Length - 1\n                    && uriComponent.IndexOf(':', index + 1) >= 0)\n                {\n                    // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                }\n                else if (uriComponent.IndexOf(\"xn--\", StringComparison.Ordinal) >= 0)\n                {\n                    // Contains punycode\n                    if (index >= 0)\n                    {\n                        // Has a port\n                        string port = uriComponent.Substring(index);\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent, 0, index) + port;\n                    }\n                    else\n                    {\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent);\n                    }\n                }\n            }\n            return new HostString(uriComponent);\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the host and port of the give Uri instance.\n        /// Punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uri\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new HostString(uri.GetComponents(\n                UriComponents.NormalizedHost | // Always convert punycode to Unicode.\n                UriComponents.HostAndPort, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Compares the equality of the Value property, ignoring case.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(HostString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares against the given object only if it is a HostString.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is HostString && Equals((HostString)obj);\n        }\n\n        /// <summary>\n        /// Gets a hash code for the value.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(HostString left, HostString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(HostString left, HostString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial interface IFormCollection : IReadableStringCollection\n    {}\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, string[]>\n    {\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        new string this[string key] { get; set; }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        IList<string> GetCommaSeparatedValues(string key);\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Append(string key, string value);\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendCommaSeparatedValues(string key, params string[] values);\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Set(string key, string value);\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetCommaSeparatedValues(string key, params string[] values);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinContext\n    {\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        IOwinRequest Request { get; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        IOwinResponse Response { get; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        TextWriter TraceOutput { get; set; }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinContext Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinRequest\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        string Method { get; set; }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        string Scheme { get; set; }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        bool IsSecure { get; }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        HostString Host { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        PathString PathBase { get; set; }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        PathString Path { get; set; }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        QueryString QueryString { get; set; }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        IReadableStringCollection Query { get; }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        Uri Uri { get; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        RequestCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        string CacheControl { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        string MediaType { get; set; }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        string Accept { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        CancellationToken CallCancelled { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        string LocalIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        int? LocalPort { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        string RemoteIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        int? RemotePort { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        ClaimsPrincipal User { get; set; }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        Task<IFormCollection> ReadFormAsync();\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinRequest Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinResponse\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        int StatusCode { get; set; }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        string ReasonPhrase { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        ResponseCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        long? ContentLength { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        DateTimeOffset? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        string ETag { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        void OnSendingHeaders(Action<object> callback, object state);\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        void Redirect(string location);\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        void Write(string text);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        void Write(byte[] data);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        void Write(byte[] data, int offset, int count);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, int offset, int count, CancellationToken token);\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinResponse Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// Accessors for headers, query, forms, etc.\n    /// </summary>\n    partial interface IReadableStringCollection : IEnumerable<KeyValuePair<string, string[]>>\n    {\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string this[string key] { get; }\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string Get(string key);\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        IList<string> GetValues(string key);\n\n        // Raw\n    }\n\n    internal static class OwinConstants\n    {\n        #region OWIN v1.0.0 - 3.2.1. Request Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string RequestScheme = \"owin.RequestScheme\";\n        public const string RequestMethod = \"owin.RequestMethod\";\n        public const string RequestPathBase = \"owin.RequestPathBase\";\n        public const string RequestPath = \"owin.RequestPath\";\n        public const string RequestQueryString = \"owin.RequestQueryString\";\n        public const string RequestProtocol = \"owin.RequestProtocol\";\n        public const string RequestHeaders = \"owin.RequestHeaders\";\n        public const string RequestBody = \"owin.RequestBody\";\n        public const string RequestUser = \"owin.RequestUser\"; //owin 1.0.1\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.2. Response Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string ResponseStatusCode = \"owin.ResponseStatusCode\";\n        public const string ResponseReasonPhrase = \"owin.ResponseReasonPhrase\";\n        public const string ResponseProtocol = \"owin.ResponseProtocol\";\n        public const string ResponseHeaders = \"owin.ResponseHeaders\";\n        public const string ResponseBody = \"owin.ResponseBody\";\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.3. Other Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string CallCancelled = \"owin.CallCancelled\";\n\n        public const string OwinVersion = \"owin.Version\";\n\n        #endregion\n\n        #region OWIN Keys for IAppBuilder.Properties\n\n        internal static class Builder\n        {\n            public const string AddSignatureConversion = \"builder.AddSignatureConversion\";\n            public const string DefaultApp = \"builder.DefaultApp\";\n        }\n\n        #endregion\n\n        #region OWIN Key Guidelines and Common Keys - 6. Common keys\n\n        // http://owin.org/spec/CommonKeys.html\n\n        internal static class CommonKeys\n        {\n            public const string ClientCertificate = \"ssl.ClientCertificate\";\n            public const string RemoteIpAddress = \"server.RemoteIpAddress\";\n            public const string RemotePort = \"server.RemotePort\";\n            public const string LocalIpAddress = \"server.LocalIpAddress\";\n            public const string LocalPort = \"server.LocalPort\";\n            public const string IsLocal = \"server.IsLocal\";\n            public const string TraceOutput = \"host.TraceOutput\";\n            public const string Addresses = \"host.Addresses\";\n            public const string AppName = \"host.AppName\";\n            public const string Capabilities = \"server.Capabilities\";\n            public const string OnSendingHeaders = \"server.OnSendingHeaders\";\n            public const string OnAppDisposing = \"host.OnAppDisposing\";\n            public const string Scheme = \"scheme\";\n            public const string Host = \"host\";\n            public const string Port = \"port\";\n            public const string Path = \"path\";\n        }\n\n        #endregion\n\n        #region SendFiles v0.3.0\n\n        // http://owin.org/extensions/owin-SendFile-Extension-v0.3.0.htm\n\n        internal static class SendFiles\n        {\n            // 3.1. Startup\n\n            public const string Version = \"sendfile.Version\";\n            public const string Support = \"sendfile.Support\";\n            public const string Concurrency = \"sendfile.Concurrency\";\n\n            // 3.2. Per Request\n\n            public const string SendAsync = \"sendfile.SendAsync\";\n        }\n\n        #endregion\n\n        #region Opaque v0.3.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class OpaqueConstants\n        {\n            // 3.1. Startup\n            public const string Version = \"opaque.Version\";\n\n            // 3.2. Per Request\n            public const string Upgrade = \"opaque.Upgrade\";\n\n            // 5. Consumption\n            public const string Stream = \"opaque.Stream\";\n            // public const string Version = \"opaque.Version\"; // redundant, declared above\n            public const string CallCancelled = \"opaque.CallCancelled\";\n        }\n\n        #endregion\n\n        #region WebSocket v0.4.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class WebSocket\n        {\n            // 3.1. Startup\n            public const string Version = \"websocket.Version\";\n\n            // 3.2. Per Request\n            public const string Accept = \"websocket.Accept\";\n\n            // 4. Accept\n            public const string SubProtocol = \"websocket.SubProtocol\";\n\n            // 5. Consumption\n            public const string SendAsync = \"websocket.SendAsync\";\n            public const string ReceiveAsync = \"websocket.ReceiveAsync\";\n            public const string CloseAsync = \"websocket.CloseAsync\";\n            // public const string Version = \"websocket.Version\"; // redundant, declared above\n            public const string CallCancelled = \"websocket.CallCancelled\";\n            public const string ClientCloseStatus = \"websocket.ClientCloseStatus\";\n            public const string ClientCloseDescription = \"websocket.ClientCloseDescription\";\n        }\n\n        #endregion\n\n        #region Security v0.1.0\n\n        // http://owin.org/extensions/owin-Security-Extension-v0.1.0.htm\n\n        internal static class Security\n        {\n            // 3.2. Per Request\n\n            public const string User = \"server.User\";\n\n            public const string Authenticate = \"security.Authenticate\";\n\n            // 3.3. Response\n\n            public const string SignIn = \"security.SignIn\";\n\n            public const string SignOut = \"security.SignOut\";\n\n            public const string SignOutProperties = \"security.SignOutProperties\";\n\n            public const string Challenge = \"security.Challenge\";\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinContext : IOwinContext\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinContext()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Create a new wrapper.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinContext(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        public virtual IOwinRequest Request { get; private set; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        public virtual IOwinResponse Response { get; private set; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        public virtual TextWriter TraceOutput\n        {\n            get { return Get<TextWriter>(OwinConstants.CommonKeys.TraceOutput); }\n            set { Set<TextWriter>(OwinConstants.CommonKeys.TraceOutput, value); }\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinContext Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinRequest : IOwinRequest\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinRequest()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Create a new environment wrapper exposing request properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinRequest(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        public virtual string Method\n        {\n            get { return Get<string>(OwinConstants.RequestMethod); }\n            set { Set(OwinConstants.RequestMethod, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        public virtual string Scheme\n        {\n            get { return Get<string>(OwinConstants.RequestScheme); }\n            set { Set(OwinConstants.RequestScheme, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        public virtual bool IsSecure\n        {\n            get { return string.Equals(Scheme, Constants.Https, StringComparison.OrdinalIgnoreCase); }\n        }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        public virtual HostString Host\n        {\n            get { return new HostString(OwinHelpers.GetHost(this)); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Host, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        public virtual PathString PathBase\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPathBase)); }\n            set { Set(OwinConstants.RequestPathBase, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        public virtual PathString Path\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPath)); }\n            set { Set(OwinConstants.RequestPath, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        public virtual QueryString QueryString\n        {\n            get { return new QueryString(Get<string>(OwinConstants.RequestQueryString)); }\n            set { Set(OwinConstants.RequestQueryString, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        public virtual IReadableStringCollection Query\n        {\n            get { return new ReadableStringCollection(OwinHelpers.GetQuery(this)); }\n        }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        public virtual Uri Uri\n        {\n            get { return new Uri(Scheme + \"://\" + Host + PathBase + Path + QueryString); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.RequestProtocol); }\n            set { Set(OwinConstants.RequestProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.RequestHeaders); }\n        }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        public RequestCookieCollection Cookies\n        {\n            get { return new RequestCookieCollection(OwinHelpers.GetCookies(this)); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        public virtual string CacheControl\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.CacheControl); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.CacheControl, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        public virtual string MediaType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.MediaType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.MediaType, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        public virtual string Accept\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Accept); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Accept, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.RequestBody); }\n            set { Set(OwinConstants.RequestBody, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        public virtual CancellationToken CallCancelled\n        {\n            get { return Get<CancellationToken>(OwinConstants.CallCancelled); }\n            set { Set(OwinConstants.CallCancelled, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        public virtual string LocalIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalIpAddress); }\n            set { Set(OwinConstants.CommonKeys.LocalIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        public virtual int? LocalPort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(LocalPortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    LocalPortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.LocalPort);\n                }\n            }\n        }\n\n        private string LocalPortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalPort); }\n            set { Set(OwinConstants.CommonKeys.LocalPort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        public virtual string RemoteIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemoteIpAddress); }\n            set { Set(OwinConstants.CommonKeys.RemoteIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        public virtual int? RemotePort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(RemotePortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    RemotePortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.RemotePort);\n                }\n            }\n        }\n\n        private string RemotePortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemotePort); }\n            set { Set(OwinConstants.CommonKeys.RemotePort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        public virtual ClaimsPrincipal User\n        {\n            get\n            {\n                var claimsPrincipal = Get<ClaimsPrincipal>(OwinConstants.RequestUser);\n                return claimsPrincipal ?? Get<IPrincipal>(OwinConstants.Security.User) as ClaimsPrincipal;\n            }\n            set { Set(OwinConstants.RequestUser, value); }\n        }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        public async Task<IFormCollection> ReadFormAsync()\n        {\n            var form = Get<IFormCollection>(\"Microsoft.Owin.Form#collection\");\n            if (form == null)\n            {\n                string text;\n                // Don't close, it prevents re-winding.\n                using (var reader = new StreamReader(Body, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4 * 1024, leaveOpen: true))\n                {\n                    text = await reader.ReadToEndAsync();\n                }\n                form = OwinHelpers.GetForm(text);\n                Set(\"Microsoft.Owin.Form#collection\", form);\n            }\n\n            return form;\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinRequest Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinResponse : IOwinResponse\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinResponse()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Creates a new environment wrapper exposing response properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinResponse(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        public virtual int StatusCode\n        {\n            get { return Get<int>(OwinConstants.ResponseStatusCode, 200); }\n            set { Set(OwinConstants.ResponseStatusCode, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        public virtual string ReasonPhrase\n        {\n            get { return Get<string>(OwinConstants.ResponseReasonPhrase); }\n            set { Set(OwinConstants.ResponseReasonPhrase, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.ResponseProtocol); }\n            set { Set(OwinConstants.ResponseProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders); }\n        }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        public virtual ResponseCookieCollection Cookies\n        {\n            get { return new ResponseCookieCollection(Headers); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        public virtual long? ContentLength\n        {\n            get\n            {\n                long value;\n                if (long.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentLength), out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentLength,\n                        value.Value.ToString(CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.ContentLength);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        public virtual DateTimeOffset? Expires\n        {\n            get\n            {\n                DateTimeOffset value;\n                if (DateTimeOffset.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Expires),\n                    CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Expires,\n                        value.Value.ToString(Constants.HttpDateFormat, CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.Expires);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        public virtual string ETag\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ETag); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ETag, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.ResponseBody); }\n            set { Set(OwinConstants.ResponseBody, value); }\n        }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public virtual void OnSendingHeaders(Action<object> callback, object state)\n        {\n            var onSendingHeaders = Get<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);\n            if (onSendingHeaders == null)\n            {\n                throw new NotSupportedException(Resources.Exception_MissingOnSendingHeaders);\n            }\n            onSendingHeaders(callback, state);\n        }\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        public virtual void Redirect(string location)\n        {\n            StatusCode = 302;\n            OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Location, location);\n        }\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        public virtual void Write(string text)\n        {\n            Write(Encoding.UTF8.GetBytes(text));\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        public virtual void Write(byte[] data)\n        {\n            Write(data, 0, data == null ? 0 : data.Length);\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        public virtual void Write(byte[] data, int offset, int count)\n        {\n            Body.Write(data, offset, count);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text)\n        {\n            return WriteAsync(text, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text, CancellationToken token)\n        {\n            return WriteAsync(Encoding.UTF8.GetBytes(text), token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data)\n        {\n            return WriteAsync(data, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, CancellationToken token)\n        {\n            return WriteAsync(data, 0, data == null ? 0 : data.Length, token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, int offset, int count, CancellationToken token)\n        {\n            return Body.WriteAsync(data, offset, count, token);\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            return Get(key, default(T));\n        }\n\n        private T Get<T>(string key, T fallback)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : fallback;\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinResponse Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct PathString : IEquatable<PathString>\n    {\n        private static readonly Func<string, string> EscapeDataString = Uri.EscapeDataString;\n\n        /// <summary>\n        /// Represents the empty path. This field is read-only.\n        /// </summary>\n        public static readonly PathString Empty = new PathString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initialize the path string with a given value. This value must be in un-escaped format. Use\n        /// PathString.FromUriComponent(value) if you have a path value which is in an escaped format.\n        /// </summary>\n        /// <param name=\"value\">The unescaped path to be assigned to the Value property.</param>\n        public PathString(string value)\n        {\n            if (!String.IsNullOrEmpty(value) && value[0] != '/')\n            {\n                throw new ArgumentException(Resources.Exception_PathMustStartWithSlash, \"value\");\n            }\n            _value = value;\n        }\n\n        /// <summary>\n        /// The unescaped path value\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the path is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrEmpty(_value); }\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public string ToUriComponent()\n        {\n            if (HasValue)\n            {\n                if (RequiresEscaping(_value))\n                {\n                    // TODO: Measure the cost of this escaping and consider optimizing.\n                    return String.Join(\"/\", _value.Split('/').Select(EscapeDataString));\n                }\n                return _value;\n            }\n            return String.Empty;\n        }\n\n        // Very conservative, these characters do not need to be escaped in a path.\n        private static bool RequiresEscaping(string value)\n        {\n            for (int i = 0; i < value.Length; i++)\n            {\n                char c = value[i];\n                // Check conservatively for safe characters. See http://www.ietf.org/rfc/rfc3986.txt\n                bool safeChar =\n                    (('a' <= c && c <= 'z')\n                    || ('A' <= c && c <= 'Z')\n                    || ('0' <= c && c <= '9')\n                    || c == '/' || c == '-' || c == '_');\n                if (!safeChar)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a path.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped path as it appears in the URI format.</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(string uriComponent)\n        {\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(Uri.UnescapeDataString(uriComponent));\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(\"/\" + uri.GetComponents(UriComponents.Path, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                return value1.Length == value2.Length || value1[value2.Length] == '/';\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <param name=\"remaining\">Any remaining segments from this instance not included in the other instance.</param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other, out PathString remaining)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                if (value1.Length == value2.Length || value1[value2.Length] == '/')\n                {\n                    remaining = new PathString(value1.Substring(value2.Length));\n                    return true;\n                }\n            }\n            remaining = Empty;\n            return false;\n        }\n\n        /// <summary>\n        /// Adds two PathString instances into a combined PathString value.\n        /// </summary>\n        /// <returns>The combined PathString value</returns>\n        public PathString Add(PathString other)\n        {\n            return new PathString(Value + other.Value);\n        }\n\n        /// <summary>\n        /// Combines a PathString and QueryString into the joined URI formatted string value.\n        /// </summary>\n        /// <returns>The joined URI formatted string value</returns>\n        public string Add(QueryString other)\n        {\n            return ToUriComponent() + other.ToUriComponent();\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value using a specific StringComparison type\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison</param>\n        /// <param name=\"comparisonType\">The StringComparison type to use</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other, StringComparison comparisonType)\n        {\n            return string.Equals(_value, other._value, comparisonType);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"obj\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is PathString && Equals((PathString)obj, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation.\n        /// </summary>\n        /// <returns>The hash code</returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public static bool operator ==(PathString left, PathString right)\n        {\n            return left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are not equal</returns>\n        public static bool operator !=(PathString left, PathString right)\n        {\n            return !left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static PathString operator +(PathString left, PathString right)\n        {\n            return left.Add(right);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static string operator +(PathString left, QueryString right)\n        {\n            return left.Add(right);\n        }\n    }\n\n    /// <summary>\n    /// Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct QueryString : IEquatable<QueryString>\n    {\n        /// <summary>\n        /// Represents the empty query string. This field is read-only.\n        /// </summary>\n        public static readonly QueryString Empty = new QueryString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initalize the query string with a given value. This value must be in escaped and delimited format without\n        /// a leading '?' character.\n        /// </summary>\n        /// <param name=\"value\">The query string to be assigned to the Value property.</param>\n        public QueryString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Initialize a query string with a single given parameter name and value. The value is\n        /// </summary>\n        /// <param name=\"name\">The unencoded parameter name</param>\n        /// <param name=\"value\">The unencoded parameter value</param>\n        public QueryString(string name, string value)\n        {\n            _value = Uri.EscapeDataString(name) + '=' + Uri.EscapeDataString(value);\n        }\n\n        /// <summary>\n        /// The unescaped query string without the leading '?' character\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the query string is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrWhiteSpace(_value); }\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentally\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public string ToUriComponent()\n        {\n            // Escape things properly so System.Uri doesn't mis-interpret the data.\n            return HasValue ? \"?\" + _value.Replace(\"#\", \"%23\") : String.Empty;\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a query.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped query as it appears in the URI format.</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(string uriComponent)\n        {\n            if (String.IsNullOrEmpty(uriComponent))\n            {\n                return new QueryString(string.Empty);\n            }\n            if (uriComponent[0] != '?')\n            {\n                throw new ArgumentException(Resources.Exception_QueryStringMustStartWithDelimiter, \"uriComponent\");\n            }\n            return new QueryString(uriComponent.Substring(1));\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new QueryString(uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped));\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(QueryString other)\n        {\n            return string.Equals(_value, other._value);\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is QueryString && Equals((QueryString)obj);\n        }\n\n        /// <summary>\n        /// Returns the hash code for this instance.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? _value.GetHashCode() : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(QueryString left, QueryString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(QueryString left, QueryString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Accessors for query, forms, etc.\n    /// </summary>\n    partial class ReadableStringCollection : IReadableStringCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public ReadableStringCollection(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetJoinedValue(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public IList<string> GetValues(string key)\n        {\n            string[] values;\n            Store.TryGetValue(key, out values);\n            return values;\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    /// <summary>\n    /// A wrapper for the request Cookie header\n    /// </summary>\n    partial class RequestCookieCollection : IEnumerable<KeyValuePair<string, string>>\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public RequestCookieCollection(IDictionary<string, string> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string> Store { get; set; }\n\n        /// <summary>\n        /// Returns null rather than throwing KeyNotFoundException\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get\n            {\n                string value;\n                Store.TryGetValue(key, out value);\n                return value;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    internal static class Resources\n    {\n        internal const string Exception_MissingOnSendingHeaders = \"The OWIN key 'server.OnSsoendingHeaders' is not available for this request.\";\n        internal const string Exception_PathMustStartWithSlash = \"The path must start with a '/' followed by one or more characters.\";\n        internal const string Exception_QueryStringMustStartWithDelimiter = \"The query string must start with a '?' unless null or empty.\";\n    }\n\n    /// <summary>\n    /// A wrapper for the response Set-Cookie header\n    /// </summary>\n    partial class ResponseCookieCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"headers\"></param>\n        public ResponseCookieCollection(IHeaderDictionary headers)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n\n            Headers = headers;\n        }\n\n        private IHeaderDictionary Headers { get; set; }\n\n        /// <summary>\n        /// Add a new cookie and value\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        public void Append(string key, string value)\n        {\n            Headers.AppendValues(Constants.Headers.SetCookie, Uri.EscapeDataString(key) + \"=\" + Uri.EscapeDataString(value) + \"; path=/\");\n        }\n\n        /// <summary>\n        /// Add a new cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        /// <param name=\"options\"></param>\n        public void Append(string key, string value, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n            bool expiresHasValue = options.Expires.HasValue;\n\n            string setCookieValue = string.Concat(\n                Uri.EscapeDataString(key),\n                \"=\",\n                Uri.EscapeDataString(value ?? string.Empty),\n                !domainHasValue ? null : \"; domain=\",\n                !domainHasValue ? null : options.Domain,\n                !pathHasValue ? null : \"; path=\",\n                !pathHasValue ? null : options.Path,\n                !expiresHasValue ? null : \"; expires=\",\n                !expiresHasValue ? null : options.Expires.Value.ToString(\"ddd, dd-MMM-yyyy HH:mm:ss \", CultureInfo.InvariantCulture) + \"GMT\",\n                !options.Secure ? null : \"; secure\",\n                !options.HttpOnly ? null : \"; HttpOnly\");\n            Headers.AppendValues(\"Set-Cookie\", setCookieValue);\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        public void Delete(string key)\n        {\n            Func<string, bool> predicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n\n            var deleteCookies = new[] { Uri.EscapeDataString(key) + \"=; expires=Thu, 01-Jan-1970 00:00:00 GMT\" };\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues == null || existingValues.Count == 0)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, deleteCookies);\n            }\n            else\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !predicate(value)).Concat(deleteCookies).ToArray());\n            }\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"options\"></param>\n        public void Delete(string key, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n\n            Func<string, bool> rejectPredicate;\n            if (domainHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"domain=\" + options.Domain, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else if (pathHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"path=\" + options.Path, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else\n            {\n                rejectPredicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n            }\n\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues != null)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !rejectPredicate(value)).ToArray());\n            }\n\n            Append(key, string.Empty, new CookieOptions\n            {\n                Path = options.Path,\n                Domain = options.Domain,\n                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),\n            });\n        }\n    }\n\n\n    static partial class IOwinResponseExtension \n    {\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"response\">The owin response</param>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public static void OnSendingHeaders<T>(this IOwinResponse response, Action<T> callback, T state)\n        {\n            if (response == null) {\n                throw new ArgumentNullException(\"response\");\n            }\n            Action<object> innerCallback = innerState => callback((T)innerState);\n            response.OnSendingHeaders(innerCallback, state);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Platform/HttpClientFactory.cs",
    "content": "namespace MicroserviceNET.Platform\n{\n  using System;\n  using System.Net.Http;\n  using System.Net.Http.Headers;\n  using System.Threading.Tasks;\n  using IdentityModel.Client;\n\n  public interface IHttpClientFactory\n  {\n    Task<HttpClient> Create(Uri uri, string requestScope);\n  }\n\n  public class HttpClientFactory : IHttpClientFactory\n  {\n    private readonly TokenClient tokenClient;\n    private readonly string correlationToken;\n    private readonly string idToken;\n\n    public HttpClientFactory(string tokenUrl, string clientName, string clientSecret, string correlationToken, string idToken)\n    {\n      this.tokenClient = new TokenClient(tokenUrl, clientName, clientSecret);\n      this.correlationToken = correlationToken;\n      this.idToken = idToken;\n    }\n\n    public async Task<HttpClient> Create(Uri uri, string requestScope)\n    {\n      var response = await this.tokenClient.RequestClientCredentialsAsync(requestScope).ConfigureAwait(false);\n      var client = new HttpClient() { BaseAddress = uri };\n      client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(\"Bearer\", response.AccessToken);\n      client.DefaultRequestHeaders.Add(\"Correlation-Token\", this.correlationToken);\n      if (!string.IsNullOrEmpty(this.idToken))\n        client.DefaultRequestHeaders.Add(\"microservice.NET-end-user\", this.idToken);\n      return client;\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Platform/MicroserviceNET.Platform.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>927b3235-8756-4b92-99df-4f8d8adae645</ProjectGuid>\n    <RootNamespace>MicroserviceNET.Platform</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Platform/MicroservicePlatformHelper.cs",
    "content": "namespace MicroserviceNET.Platform\n{\n  using System.Security.Claims;\n  using Nancy;\n  using Nancy.Owin;\n  using Nancy.TinyIoc;\n  using LibOwin;\n\n  public static class MicroservicePlatform\n  {\n    private static string TokenUrl;\n    private static string ClientName;\n    private static string ClientSecret;\n\n    public static void Configure(string tokenUrl, string clientName, string clientSecret)\n    {\n      TokenUrl = tokenUrl;\n      ClientName = clientName;\n      ClientSecret = clientSecret;\n    }\n\n    public static TinyIoCContainer UseHttpClientFactory(this TinyIoCContainer self, NancyContext context)\n    {\n      var correlationToken =\n        context.GetOwinEnvironment()?[\"correlationToken\"] as string;\n      object key = null;\n      context.GetOwinEnvironment()?.TryGetValue(OwinConstants.RequestUser, out key);\n      var principal = key as ClaimsPrincipal;\n      var idToken = principal?.FindFirst(\"id_token\");\n      self.Register<IHttpClientFactory>(new HttpClientFactory(TokenUrl, ClientName, ClientSecret, correlationToken ?? \"\", idToken?.Value ?? \"\"));\n      return self;\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter11/MicroserviceNET.Platform/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n\n  \"dependencies\": {\n    \"NETStandard.Library\": \"1.5.0\",\n    \"MicroserivceNET.Auth\": {\n      \"target\": \"project\"\n    },\n    \"MicroserviceNET.Logging\": {\n      \"target\": \"project\",\n      \"version\": \"1.0.0\"\n    },\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"IdentityModel\": \"2.0.0-beta5\"\n  },\n\n  \"frameworks\": {\n    \"netstandard1.5\": {\n      \"imports\": \"dnxcore50\"\n    }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"MicroserviceNET.Platform\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter11/ch11.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25123.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"MicroserviceNET.Logging\", \"MicroserviceNET.Logging\\MicroserviceNET.Logging.xproj\", \"{F73DF2AB-708B-4916-AC28-E95117466511}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"MicroserivceNET.Auth\", \"MicroserivceNET.Auth\\MicroserivceNET.Auth.xproj\", \"{662415B4-3486-4B64-B1F9-718B9FF0879D}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"MicroserviceNET.Platform\", \"MicroserviceNET.Platform\\MicroserviceNET.Platform.xproj\", \"{927B3235-8756-4B92-99DF-4F8D8ADAE645}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"HelloMicroservicesPlatform\", \"HelloMicroservicesPlatform\\HelloMicroservicesPlatform.xproj\", \"{DAEBD923-B213-4CA5-A240-B96686AEC974}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{F73DF2AB-708B-4916-AC28-E95117466511}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{F73DF2AB-708B-4916-AC28-E95117466511}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{F73DF2AB-708B-4916-AC28-E95117466511}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{F73DF2AB-708B-4916-AC28-E95117466511}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{662415B4-3486-4B64-B1F9-718B9FF0879D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{662415B4-3486-4B64-B1F9-718B9FF0879D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{662415B4-3486-4B64-B1F9-718B9FF0879D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{662415B4-3486-4B64-B1F9-718B9FF0879D}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{927B3235-8756-4B92-99DF-4F8D8ADAE645}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{927B3235-8756-4B92-99DF-4F8D8ADAE645}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{927B3235-8756-4B92-99DF-4F8D8ADAE645}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{927B3235-8756-4B92-99DF-4F8D8ADAE645}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{DAEBD923-B213-4CA5-A240-B96686AEC974}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{DAEBD923-B213-4CA5-A240-B96686AEC974}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{DAEBD923-B213-4CA5-A240-B96686AEC974}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{DAEBD923-B213-4CA5-A240-B96686AEC974}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/Chapter12/.idea.C12/riderModule.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"RIDER_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\">\n    <content url=\"file://$MODULE_DIR$/..\">\n      <sourceFolder url=\"file://$MODULE_DIR$/..\" isTestSource=\"false\" />\n    </content>\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n  </component>\n</module>"
  },
  {
    "path": "src/Chapter12/ApiGateway/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter12/ApiGateway/Dockerfile",
    "content": "FROM microsoft/dotnet:latest\n\nCOPY . /app\n\nWORKDIR /app\n\nRUN [\"dotnet\", \"restore\"]\n\nRUN [\"dotnet\", \"build\"]\n\nEXPOSE 5000/tcp\n\nENTRYPOINT [\"dotnet\", \"run\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter12/ApiGateway/GatewayModule.cs",
    "content": "namespace ApiGateway\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using System.Threading.Tasks;\n  using System.Net.Http;\n  using MicroserviceNET.Platform;\n  using Nancy;\n  using Nancy.ModelBinding;\n  using Newtonsoft.Json;\n  using Serilog;\n  using static System.Text.Encoding;\n\n  public class GatewayModule : NancyModule\n  {\n    private static Product[] productList = new[] { new Product { ProductName = \"Fancy shirt\", ProductId = 1 }, new Product { ProductName = \"Fancier shirt\", ProductId = 2 } };\n\n    public GatewayModule(IHttpClientFactory clientFactory, ILogger logger)\n    {\n      Get(\"/productlist\", async parameters => \n      {\n        var userId = (int)parameters.userid;\n\n        var client = await clientFactory.Create(new Uri(\"http://localhost:5100/\"), \"product_catalog_read\");\n        var response = await client.GetAsync(\"/products?productIds=1,2,3,4\");\n        var content = await response?.Content.ReadAsStringAsync();\n        logger.Information(content);\n        productList =\n          JsonConvert.DeserializeObject<List<Product>>(content).ToArray();\n\n        client = await clientFactory.Create(new Uri(\"http://localhost:5200/\"), \"shopping_cart_write\");\n        response = await client.GetAsync($\"/shoppingcart/{userId}\");\n        content = await response?.Content.ReadAsStringAsync();\n        logger.Information(content);\n        var basketProducts = GetBasketProductsFromResponse(content);\n\n        return View[\"productlist\", new { ProductList = productList, BasketProducts = basketProducts }];\n      });\n\n      Post(\"/shoppingcart/{userid}\", async parameters =>\n      {\n        var productId = this.Bind<int>();\n        var userId = (int) parameters.userid;\n\n        var client = await clientFactory.Create(new Uri(\"http://localhost:5200/\"), \"shopping_cart_write\");\n        var response =  await\n          client.PostAsync(\n            $\"/shoppingcart/{userId}/items\",\n            new StringContent(JsonConvert.SerializeObject(new[] { productId }), UTF8, \"application/json\"));\n        var content = await response?.Content.ReadAsStringAsync();\n        logger.Information(content);\n        var basketProducts = GetBasketProductsFromResponse(content);\n\n        logger.Information(\"{@basket}\", basketProducts);\n        return View[\"productlist\", new { ProductList = productList, BasketProducts = basketProducts }];\n      });\n\n      Delete(\"/shoppingcart/{userid}\", async parameters =>\n      {\n        var productId = this.Bind<int>();\n        var userId = (int) parameters.userid;\n\n        HttpClient client = await clientFactory.Create(new Uri(\"http://localhost:5200/\"), \"shopping_cart_write\");\n        var request = new HttpRequestMessage(HttpMethod.Delete, $\"/shoppingcart/{userId}/items\")\n        {\n          Content = new StringContent(JsonConvert.SerializeObject(new[] { productId }), UTF8, \"application/json\")\n        };\n        var response = await client.SendAsync(request);\n        var content = await response?.Content.ReadAsStringAsync();\n        logger.Information(content);\n        var basketProducts = GetBasketProductsFromResponse(content);\n\n        logger.Information(\"{@basket}\", basketProducts);\n        return View[\"productlist\", new { ProductList = productList, BasketProducts = basketProducts }];\n      });\n    }\n\n    private List<Product> GetBasketProductsFromResponse(string responseBody)\n    {\n      return JsonConvert.DeserializeObject<ShoppingCart>(responseBody)\n                        .Items\n                        ?.Select(item =>\n                                   new Product {ProductName = item.ProductName, ProductId = item.ProductCatalogueId})\n                        ?.ToList() ?? new List<Product>();\n    }\n  }\n  \n  public class Product\n  {\n    public string ProductName;\n    public int ProductId;\n  }\n  \n      public class ShoppingCart\n      {\n        public IEnumerable<ShoppingCartItem> Items { get; set; }\n      }\n\n      public class ShoppingCartItem\n      {\n        public int ProductCatalogueId { get; set;}\n        public string ProductName { get; set; }\n      }\n}"
  },
  {
    "path": "src/Chapter12/ApiGateway/Program.cs",
    "content": "using System.IO;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\n\nnamespace ApiGateway\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n           var config = new ConfigurationBuilder()\n                .AddEnvironmentVariables(prefix: \"ASPNETCORE_\")\n                .Build();\n            \n            var host = new WebHostBuilder()\n                .UseConfiguration(config)\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter12/ApiGateway/Properties/launchSettings.json",
    "content": "{\n  \"profiles\": {\n    \"ApiGateway\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ApiGateway/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter12/ApiGateway/Startup.cs",
    "content": "namespace ApiGateway\n{\n  using System.Threading.Tasks;\n  using MicroserviceNET.Logging;\n  using MicroserviceNET.Platform;\n  using MicroserviceNET.Auth;\n  using Microsoft.AspNetCore.Builder;\n  using Nancy;\n  using Nancy.Bootstrapper;\n  using Nancy.Owin;\n  using Nancy.TinyIoc;\n  using Serilog;\n  using Serilog.Events;\n\n  public class Startup\n  {\n    public void Configure(IApplicationBuilder app)\n    {\n      var logger = ConfigureLogger();\n      app.UseStaticFiles();\n      app.UseOwin()\n        .UseMonitoringAndLogging(logger, HealtCheck)\n        .UseNancy(opt => opt.Bootstrapper = new Bootstrapper(logger));\n    }\n\n    private ILogger ConfigureLogger()\n    {      \n      MicroservicePlatform.Configure(\n        tokenUrl: \"http://localhost:5001/\",\n        clientName:\"api_gateway\",\n        clientSecret: \"secret\");\n      return new LoggerConfiguration()\n        .Enrich.FromLogContext()\n        .WriteTo.ColoredConsole(\n          LogEventLevel.Verbose,\n          \"{NewLine}{Timestamp:HH:mm:ss} [{Level}] ({CorrelationToken}) {Message}{NewLine}{Exception}\")\n        .CreateLogger();\n    }\n\n    private static Task<bool> HealtCheck()\n    {\n        return Task.FromResult(true);\n    }\n }\n \n  public class Bootstrapper : DefaultNancyBootstrapper\n  {\n    private ILogger logger;\n    public Bootstrapper(ILogger logger)\n    {\n      this.logger = logger;\n    }\n    protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)\n    {\n      base.ApplicationStartup(container, pipelines);\n      container.Register(logger);\n      container.UseHttpClientFactory(new NancyContext());\n    }\n\n    protected override void RequestStartup(\n      TinyIoCContainer container,\n      IPipelines pipelines,\n      NancyContext context)\n    {\n      base.RequestStartup(container, pipelines, context);\n      container.UseHttpClientFactory(context);\n    }\n  }\n\n  public class CustomRootPathProvider : IRootPathProvider\n  {\n      public string GetRootPath()\n      {\n          return @\"C:\\Users\\chors_000\\Documents\\horsdal\\code\\Chapter12\\ApiGateway\";\n      }\n  }\n}\n\n"
  },
  {
    "path": "src/Chapter12/ApiGateway/productlist.sshtml",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<link rel=\"stylesheet\" \nhref=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css\" \nintegrity=\"sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7\" \ncrossorigin=\"anonymous\">\n<title>MicroCommerce.NET</title>\n</head>\n<body>\n<div class=\"container\">\n<div class=\"page-header\"><h1>MicroCommerce <small> - Product List</small></h1></div>\n<div class=\"row\">\n<div class=\"col-md-8\">\n  @Each.ProductList \n  <div class=\"row\" style=\"background-color: #eee; border-bottom-style: solid\">\n    <div class=\"col-md-8\">\n      <h4>@Current.ProductName</h4>\n      <p>lorem ipsum</p>\n    </div>\n    <div class=\"col-md-4\"><p></p><button class=\"btn btn-primary\" type=\"button\" onclick=\"buy(@Current.ProductId);\">BUY!</button></div>\n  </div>\n  @EndEach\n</div>\n<div class=\"col-md-4\">\n  <div class=\"panel panel-info\">\n    <div class=\"panel-heading\">Shopping Cart</div>\n    <div class=\"panel-body\">\n      @Each.BasketProducts\n        <div>\n          @Current.ProductName\n          <button class=\"btn btn-link\" onclick=\"removeFromBasket(@Current.ProductId);\">\n            <span class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"></span>\n          </button>\n        </div>\n      @EndEach\n    </div>\n  </div>\n</div>\n</div>\n</div>\n</body>\n<script>\nfunction buy(productId) {\n  var xhttp = new XMLHttpRequest();\n  xhttp.onreadystatechange = function() {\n    if (xhttp.readyState == 4 && xhttp.status == 200) {\n      document.write(xhttp.responseText);\n      document.close();\n    }\n  }\n  xhttp.open('POST', '/shoppingcart/123', true);\n  xhttp.setRequestHeader('Content-type', 'application/json');\n  xhttp.send( JSON.stringify(productId));\n}\n\nfunction removeFromBasket(productId) {\n  var xhttp = new XMLHttpRequest();\n  xhttp.onreadystatechange = function() {\n    if (xhttp.readyState == 4 && xhttp.status == 200) {\n      document.write(xhttp.responseText);\n      document.close();\n    }\n  }\n  xhttp.open('DELETE', '/shoppingcart/123', true);\n  xhttp.setRequestHeader('Content-type', 'application/json');\n  xhttp.send(JSON.stringify(productId));\n}\n</script>\n</html>"
  },
  {
    "path": "src/Chapter12/ApiGateway/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Microsoft.AspNetCore.StaticFiles\": \"1.0.0\",\n    \"System.Text.Encoding\": \"4.0.11\", \n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"MicroserviceNET.Platform\": { \"target\": \"project\" },\n    \"Serilog.Sinks.ColoredConsole\": \"2.0.0-beta-700\"\n  },\n\n  \"tools\": {\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"configProperties\": {\n      \"System.GC.Server\": true\n    }\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"ApiGateway\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ApiGateway/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter12/Login/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter12/Login/Configuration/Clients.cs",
    "content": "﻿namespace Login.Configuration\n{\n  using System.Collections.Generic;\n  using IdentityServer4.Models;\n\n  public class Clients\n  {\n    public static IEnumerable<Client> Get() =>\n      new List<Client>\n      {\n        new Client\n        {\n          ClientName = \"API Gateway\",\n          ClientId = \"api_gateway\",\n          ClientSecrets = new List<Secret>\n          {\n            new Secret(\"secret\".Sha256())\n          },\n          AllowedScopes = new List<string>\n          {\n            \"loyalty_program_write\",\n          },\n          AllowedGrantTypes = GrantTypes.ClientCredentials\n        },\n\n        new Client\n        {\n          ClientName = \"Web Client\",\n          ClientId = \"web\",\n\n          RedirectUris = new List<string>\n          {\n            \"http://localhost:5003/signin-oidc\",\n          },\n          PostLogoutRedirectUris = new List<string>\n          {\n            \"http://localhost:5003/\",\n          },\n\n          AllowedScopes = new List<string>\n          {\n                        \"openid\",\n                        \"email\",\n                        \"profile\",\n          }\n        }\n      };\n  }\n}"
  },
  {
    "path": "src/Chapter12/Login/Configuration/Scopes.cs",
    "content": "﻿namespace Login.Configuration\n{\n  using System.Collections.Generic;\n  using IdentityServer4.Models;\n\n  public class Scopes\n  {\n    public static IEnumerable<Scope> Get() =>\n      new[]\n      {\n        // standard OpenID Connect scopes\n        StandardScopes.OpenId,\n        StandardScopes.ProfileAlwaysInclude,\n        StandardScopes.EmailAlwaysInclude,\n        new Scope\n        {\n          Name = \"loyalty_program_write\",\n          DisplayName = \"Loyalty Program write access\",\n          Type = ScopeType.Resource,\n        }\n      };\n  }\n}"
  },
  {
    "path": "src/Chapter12/Login/Configuration/Users.cs",
    "content": "﻿namespace Login.Configuration\n{\n  using System.Collections.Generic;\n  using System.Security.Claims;\n  using IdentityModel;\n  using IdentityServer4.Services.InMemory;\n\n  static class Users\n  {\n    public static List<InMemoryUser> Get()\n      =>\n        new List<InMemoryUser>\n        {\n          new InMemoryUser{Subject = \"818727\", Username = \"alice\", Password = \"alice\",\n            Claims = new[]\n            {\n              new Claim(JwtClaimTypes.Name, \"Alice Smith\"),\n              new Claim(JwtClaimTypes.GivenName, \"Alice\"),\n              new Claim(JwtClaimTypes.FamilyName, \"Smith\"),\n              new Claim(JwtClaimTypes.Email, \"AliceSmith@email.com\"),\n              new Claim(JwtClaimTypes.EmailVerified, \"true\", ClaimValueTypes.Boolean),\n              new Claim(JwtClaimTypes.Role, \"User\"),\n              new Claim(JwtClaimTypes.Id, \"1\", ClaimValueTypes.Integer64)\n            }\n          },\n          new InMemoryUser{Subject = \"88421113\", Username = \"bob\", Password = \"bob\",\n            Claims = new[]\n            {\n              new Claim(JwtClaimTypes.Name, \"Bob Smith\"),\n              new Claim(JwtClaimTypes.GivenName, \"Bob\"),\n              new Claim(JwtClaimTypes.FamilyName, \"Smith\"),\n              new Claim(JwtClaimTypes.Email, \"BobSmith@email.com\"),\n              new Claim(JwtClaimTypes.EmailVerified, \"true\", ClaimValueTypes.Boolean),\n              new Claim(JwtClaimTypes.Role, \"User\"),\n              new Claim(JwtClaimTypes.Id, \"2\", ClaimValueTypes.Integer64)\n            }\n          }\n        };\n  }\n}"
  },
  {
    "path": "src/Chapter12/Login/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter12/Login/Login.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>f416d0b1-71ee-400e-91e2-fc2b047da208</ProjectGuid>\n    <RootNamespace>Login</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter12/Login/Program.cs",
    "content": "namespace Login\n{\n  using System.IO;\n  using Microsoft.AspNetCore.Hosting;\n\n  public class Program\n  {\n    public static void Main(string[] args)\n    {\n      var host = new WebHostBuilder()\n        .UseKestrel()\n        .UseContentRoot(Directory.GetCurrentDirectory())\n        .UseIISIntegration()\n        .UseStartup<Startup>()\n        .UseUrls(\"http://localhost:5001\")\n        .Build();\n\n      host.Run();\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/Login/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"IdentityServer\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/Login/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter12/Login/Startup.cs",
    "content": "﻿namespace Login\n{\n  using System.IO;\n  using Microsoft.AspNetCore.Builder;\n  using Microsoft.AspNetCore.Hosting;\n  using System.Security.Cryptography.X509Certificates;\n  using Microsoft.AspNetCore.Http;\n  using Microsoft.Extensions.Logging;\n  using Microsoft.Extensions.DependencyInjection;\n\n  using Configuration;\n\n  public class Startup\n  {\n    private readonly IHostingEnvironment environment;\n\n    public Startup(IHostingEnvironment env)\n    {\n      this.environment = env;\n    }\n\n    public void ConfigureServices(IServiceCollection services)\n    {\n      var cert = new X509Certificate2(Path.Combine(this.environment.ContentRootPath, \"idsrv3test.pfx\"), \"idsrv3test\");\n\n      services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();\n      var builder = services\n        .AddIdentityServer()\n        .SetSigningCredential(cert)\n        .AddInMemoryClients(Clients.Get())\n        .AddInMemoryScopes(Scopes.Get())\n        .AddInMemoryUsers(Users.Get());\n\n      services.AddMvc();\n    }\n\n    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)\n    {\n      loggerFactory.AddConsole(LogLevel.Trace);\n      loggerFactory.AddDebug(LogLevel.Trace);\n\n      app.UseCookieAuthentication(new CookieAuthenticationOptions\n      {\n        AuthenticationScheme = \"Temp\",\n        AutomaticAuthenticate = false,\n        AutomaticChallenge = false\n      });\n\n      app.UseIdentityServer();\n\n      app.UseStaticFiles();\n      app.UseMvcWithDefaultRoute();\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/Login/project.json",
    "content": "  {\n    \"dependencies\": {\n      \"Microsoft.NETCore.App\": {\n        \"version\": \"1.0.0\",\n        \"type\": \"platform\"\n      },\n      \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n      \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n      \"Microsoft.AspNetCore.StaticFiles\": \"1.0.0\",\n      \"Microsoft.AspNetCore.Mvc\": \"1.0.0\",\n      \"Microsoft.Extensions.Logging.Console\": \"1.0.0\",\n      \"Microsoft.Extensions.Logging.Debug\": \"1.0.0\",\n      \"IdentityServer4\": \"1.0.0-beta5\",\n      \"SeriLog\": \"2.0.0-rc-600\"\n    },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"IdentityServer\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/Login/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter12/ProductCatalog/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter12/ProductCatalog/Dockerfile",
    "content": "FROM microsoft/dotnet:latest\n\nCOPY . /app\n\nWORKDIR /app\n\nRUN [\"dotnet\", \"restore\"]\n\nRUN [\"dotnet\", \"build\"]\n\nEXPOSE 5000/tcp\n\nENTRYPOINT [\"dotnet\", \"run\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter12/ProductCatalog/ProductsModule.cs",
    "content": "namespace ProductCatalog\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Linq;\n  using Nancy;\n  \n  public class ProductsModule : NancyModule\n  {\n    public ProductsModule(ProductStore productStore) : base(\"/products\")\n    {\n      Get(\"\", _ =>\n      {\n        string productIdsString = this.Request.Query.productIds;\n        var productIds = ParseProductIdsFromQueryString(productIdsString);\n        var products = productStore.GetProductsByIds(productIds);\n\n        return\n          this\n           .Negotiate\n           .WithModel(products)\n           .WithHeader(\"cache-control\", \"max-age:86400\");\n      });\n    }\n\n    private static IEnumerable<int> ParseProductIdsFromQueryString(string productIdsString)\n    {\n        return productIdsString.Split(',').Select(s => s.Replace(\"[\", \"\").Replace(\"]\", \"\")).Select(int.Parse);\n    }\n  }\n\n  public interface ProductStore\n  {\n      IEnumerable<ProductCatalogProduct> GetProductsByIds(IEnumerable<int> productIds);\n  }\n\n  public class StaticProductStore : ProductStore\n  {\n    public IEnumerable<ProductCatalogProduct> GetProductsByIds(IEnumerable<int> productIds)\n    {\n      return productIds.Select(id => new ProductCatalogProduct(id, \"Product no. \" + id, \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum\", new Money()));\n    }\n  }\n\n  public class ProductCatalogProduct                                \n  {\n    public ProductCatalogProduct(int productId, string productName, string description, Money price)\n    {\n        this.ProductId = productId.ToString();\n        this.ProductName = productName;\n        this.ProductDescription = description;\n        this.Price = price;\n    }\n    public string ProductId { get; private set; }\n    public string ProductName { get; private set; }\n    public string ProductDescription { get; private set; }\n    public Money Price { get; private set; }\n  }\n    \n  public class Money { }\n}"
  },
  {
    "path": "src/Chapter12/ProductCatalog/Program.cs",
    "content": "namespace ProductCatalog\n{\n  using System.IO;\n  using Microsoft.AspNetCore.Hosting;\n  using Microsoft.Extensions.Configuration;\n  public class Program\n  {\n    public static void Main(string[] args)\n    {\n      var config = new ConfigurationBuilder()\n           .AddEnvironmentVariables(prefix: \"ASPNETCORE_\")\n           .Build();\n       \n       var host = new WebHostBuilder()\n           .UseConfiguration(config)\n           .UseKestrel()\n           .UseUrls(\"http://localhost:5100\")\n           .UseContentRoot(Directory.GetCurrentDirectory())\n           .UseIISIntegration()\n           .UseStartup<Startup>()\n           .Build();\n      host.Run();\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ProductCatalog/Properties/launchSettings.json",
    "content": "{\n  \"profiles\": {\n    \"ProductCatalog\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ProductCatalog/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter12/ProductCatalog/Startup.cs",
    "content": "namespace ProductCatalog\n{\n  using Microsoft.AspNetCore.Builder;\n  using Microsoft.AspNetCore.Hosting;\n  using Microsoft.Extensions.Logging;\n  using Nancy.Owin;\n  \n  public class Startup\n  {\n    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)\n    {\n      app.UseOwin().UseNancy();\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ProductCatalog/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\"\n  },\n\n  \"tools\": {\n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"configProperties\": {\n      \"System.GC.Server\": true\n    }\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"ProductCatalog\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ProductCatalog/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/.vscode/launch.json",
    "content": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \".NET Core Launch (console)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/ShoppingCart.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false\n        },\n        {\n            \"name\": \".NET Core Launch (web)\",\n            \"type\": \"coreclr\",\n            \"request\": \"launch\",\n            \"preLaunchTask\": \"build\",\n            \"program\": \"${workspaceRoot}/bin/Debug/netcoreapp1.0/ShoppingCart.dll\",\n            \"args\": [],\n            \"cwd\": \"${workspaceRoot}\",\n            \"stopAtEntry\": false,\n            \"launchBrowser\": {\n                \"enabled\": true,\n                \"args\": \"${auto-detect-url}\",\n                \"windows\": {\n                    \"command\": \"cmd.exe\",\n                    \"args\": \"/C start ${auto-detect-url}\"\n                },\n                \"osx\": {\n                    \"command\": \"open\"\n                },\n                \"linux\": {\n                    \"command\": \"xdg-open\"\n                }\n            }\n        },\n        {\n            \"name\": \".NET Core Attach\",\n            \"type\": \"coreclr\",\n            \"request\": \"attach\",\n            \"processName\": \"<example>\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/.vscode/tasks.json",
    "content": "{\n    \"version\": \"0.1.0\",\n    \"command\": \"dotnet\",\n    \"isShellCommand\": true,\n    \"args\": [],\n    \"tasks\": [\n        {\n            \"taskName\": \"build\",\n            \"args\": [],\n            \"isBuildCommand\": true,\n            \"problemMatcher\": \"$msCompile\"\n        }\n    ]\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/EventFeed/Event.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using System;\n\n  public struct Event\n  {\n    public long SequenceNumber { get; }\n    public DateTimeOffset OccuredAt { get; }\n    public string Name { get; }\n    public object Content { get; }\n\n    public Event(\n      long sequenceNumber,\n      DateTimeOffset occuredAt,\n      string name,\n      object content)\n    {\n      this.SequenceNumber = sequenceNumber;\n      this.OccuredAt = occuredAt;\n      this.Name = name;\n      this.Content = content;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/EventFeed/EventStore.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n    using System;\n    using System.Text;\n    using System.Collections.Generic;\n    using System.Data.SqlClient;\n    using System.Linq;\n    using System.Threading.Tasks;\n    using Dapper;\n    using Newtonsoft.Json;\n#if net461\n  using global::EventStore.ClientAPI;\n#endif\n  public class EventStore : IEventStore\n  {\n    private static long currentSequenceNumber = 0;\n    private static readonly IList<Event> database = new List<Event>();\n#if net461\n    private const string connectionString =\n     \"ConnectTo=discover://admin:changeit@127.0.0.1:2112/\";\n    private IEventStoreConnection connection =\n      EventStoreConnection.Create(connectionString);\n      \n    public async Task Raise(string eventName, object content)\n    {\n      await connection.ConnectAsync().ConfigureAwait(false);\n      var contentJson = JsonConvert.SerializeObject(content);\n      var metaDataJson =\n        JsonConvert.SerializeObject(new EventMetadata\n        {\n          OccuredAt = DateTimeOffset.Now,\n          EventName = eventName\n        });\n\n      var eventData = new EventData(\n        Guid.NewGuid(),\n        \"ShoppingCartEvent\",\n        isJson: true,\n        data: Encoding.UTF8.GetBytes(contentJson),\n        metadata: Encoding.UTF8.GetBytes(metaDataJson)\n      );\n\n      await\n        connection.AppendToStreamAsync(\n          \"ShoppingCart\",\n          ExpectedVersion.Any,\n           eventData);\n    }\n    \n    public async Task<IEnumerable<Event>> GetEvents(\n      long firstEventSequenceNumber,\n      long lastEventSequenceNumber)\n    {\n      await connection.ConnectAsync().ConfigureAwait(false);\n\n      var result = await connection.ReadStreamEventsForwardAsync(\n        \"ShoppingCart\",\n        start:(int) firstEventSequenceNumber,\n        count: (int) (lastEventSequenceNumber - firstEventSequenceNumber),\n        resolveLinkTos: false).ConfigureAwait(false);\n\n      return\n        result.Events\n          .Select(ev =>\n            new\n            {\n              Content = JsonConvert.DeserializeObject(\n                Encoding.UTF8.GetString(ev.Event.Data)),\n              Metadata = JsonConvert.DeserializeObject<EventMetadata>(\n                Encoding.UTF8.GetString(ev.Event.Data))\n            })\n          .Select((ev, i) =>\n            new Event(\n              i + firstEventSequenceNumber,\n              ev.Metadata.OccuredAt,\n              ev.Metadata.EventName,\n              ev.Content));\n    }\n        \n    private class EventMetadata\n    {\n      public DateTimeOffset OccuredAt { get; set; }\n      public string EventName { get; set; }\n    }\n#else\n    private string connectionString =\n      @\"Data Source=.\\SQLEXPRESS;Initial Catalog=ShoppingCart;Integrated Security=True\";\n\n    private const string writeEventSql =\n      @\"insert into EventStore(Name, OccuredAt, Content) values (@Name, @OccuredAt, @Content)\";\n    public Task Raise(string eventName, object content)\n    {\n      var jsonContent = JsonConvert.SerializeObject(content);\n      using (var conn = new SqlConnection(connectionString))\n      {\n        return\n          conn.ExecuteAsync(\n            writeEventSql,\n            new\n            {\n              Name = eventName,\n              OccuredAt = DateTimeOffset.Now,\n              Content = jsonContent\n            });\n      }\n    }\n    \n    private const string readEventsSql =\n      @\"select * from EventStore where ID >= @Start and ID <= @End\";\n\n    public async Task<IEnumerable<Event>> GetEvents(\n      long firstEventSequenceNumber,\n      long lastEventSequenceNumber)\n    {\n      using (var conn = new SqlConnection(connectionString))\n      {\n        return (await conn.QueryAsync<dynamic>(\n          readEventsSql,\n          new\n          {\n            Start = firstEventSequenceNumber,\n            End = lastEventSequenceNumber\n          }).ConfigureAwait(false))\n          .Select(row =>\n          {\n            var content = JsonConvert.DeserializeObject(row.Content);\n            return new Event(row.ID, row.OccuredAt, row.Name, content);\n          });\n      }\n    }\n#endif\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/EventFeed/EventsFeedModule.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n{\n  using Nancy;\n\n  public class EventsFeedModule : NancyModule\n  {\n    public EventsFeedModule(IEventStore eventStore) : base(\"/events\")\n    {\n      Get(\"/\", _ =>\n      {\n        long firstEventSequenceNumber, lastEventSequenceNumber;\n        if (!long.TryParse(this.Request.Query.start.Value, \n          out firstEventSequenceNumber))\n          firstEventSequenceNumber = 0;\n        if (!long.TryParse(this.Request.Query.end.Value, \n          out lastEventSequenceNumber))\n          lastEventSequenceNumber = long.MaxValue;\n\n        return \n          eventStore.GetEvents(\n            firstEventSequenceNumber,\n            lastEventSequenceNumber);\n      });\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/EventFeed/IEventStore.cs",
    "content": "﻿namespace ShoppingCart.EventFeed\n  {\n  using System.Collections.Generic;\n  using System.Threading.Tasks;\n    \n  public interface IEventStore\n  {\n    Task<IEnumerable<Event>> GetEvents(long firstEventSequenceNumber, \n      long lastEventSequenceNumber);\n    Task Raise(string eventName, object content);\n  }\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/ICache.cs",
    "content": "namespace ShoppingCart\n{\n    using System;\n    using System.Collections.Concurrent;\n    using System.Collections.Generic;\n\n  public interface ICache  \n  {\n    void Add(string key, object value, TimeSpan ttl);\n    object Get(string productsResource);\n  }\n\n  public class Cache : ICache\n  {\n    private static IDictionary<string, Tuple<DateTimeOffset, object>> cache = new ConcurrentDictionary<string, Tuple<DateTimeOffset, object>>();      \n      \n    public void Add(string key, object value, TimeSpan ttl)\n    {\n      cache[key] = Tuple.Create(DateTimeOffset.UtcNow.Add(ttl), value);\n    }\n\n    public object Get(string productsResource)\n    {\n      Tuple<DateTimeOffset, object> value;\n      if (cache.TryGetValue(productsResource, out value) && value.Item1 > DateTimeOffset.UtcNow)\n        return value;\n      cache.Remove(productsResource);\n      return null;\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/IProductCatalogueClient.cs",
    "content": "﻿namespace ShoppingCart\n{\n  using System.Collections.Generic;\n  using System.Threading.Tasks;\n  using ShoppingCart;\n\n  public interface IProductCatalogueClient\n  {\n    Task<IEnumerable<ShoppingCartItem>>\n      GetShoppingCartItems(int[] productCatalogueIds);\n  }\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/ProductCatalogueClient.cs",
    "content": "﻿namespace ShoppingCart\n{\n    using System;\n    using System.Collections.Generic;\n    using System.Linq;\n    using System.Threading.Tasks;\n    using System.Net.Http;\n    using System.Threading;\n    using Newtonsoft.Json;\n    using Polly;\n    using ShoppingCart;\n    using System.Net.Http.Headers;\n\n    public class ProductCatalogueClient : IProductCatalogueClient\n  {\n    private static Policy exponentialRetryPolicy =\n      Policy\n        .Handle<Exception>()\n        .WaitAndRetryAsync(\n          3, \n          attempt => TimeSpan.FromMilliseconds(100 * Math.Pow(2, attempt)), (ex, _) => Console.WriteLine(ex.ToString()));\n\n    private static string productCatalogueBaseUrl =\n      @\"http://private-05cc8-chapter2productcataloguemicroservice.apiary-mock.com\";\n    private static string getProductPathTemplate =\n      \"/products?productIds=[{0}]\";\n    private readonly ICache cache;  \n    \n    public ProductCatalogueClient(ICache cache)\n    {\n      this.cache = cache;\n    }\n\n    public Task<IEnumerable<ShoppingCartItem>>\n      GetShoppingCartItems(int[] productCatalogueIds) =>\n      exponentialRetryPolicy\n        .ExecuteAsync(() => GetItemsFromCatalogueService(productCatalogueIds));\n\n    private async Task<IEnumerable<ShoppingCartItem>>\n      GetItemsFromCatalogueService(int[] productCatalogueIds)\n    {\n      var response = await\n        RequestProductFromProductCatalogue(productCatalogueIds).ConfigureAwait(false);\n      return await ConvertToShoppingCartItems(response).ConfigureAwait(false);\n    }\n\n    private async Task<HttpResponseMessage> RequestProductFromProductCatalogue(int[] productCatalogueIds)\n    {\n      var productsResource = string.Format(\n        getProductPathTemplate, string.Join(\",\", productCatalogueIds));\n      var response = this.cache.Get(productsResource) as HttpResponseMessage;\n      if (response == null)\n      {\n        using (var httpClient = new HttpClient())\n        {\n          httpClient.BaseAddress = new Uri(productCatalogueBaseUrl);\n          response = await httpClient.GetAsync(productsResource).ConfigureAwait(false);\n          AddToCache(productsResource, response);\n        }\n      }\n      return response;\n    }\n    \n    private void AddToCache(string resource, HttpResponseMessage response)\n    {\n      var cacheHeader = response\n        .Headers\n        .FirstOrDefault(h => h.Key == \"cache-control\");\n      if (string.IsNullOrEmpty(cacheHeader.Key))\n        return;\n      var maxAge =\n        CacheControlHeaderValue.Parse(cacheHeader.Value.ToString())\n          .MaxAge;\n      if (maxAge.HasValue)\n        this.cache.Add(key: resource, value: response, ttl: maxAge.Value);\n    }\n\n    private static async Task<IEnumerable<ShoppingCartItem>> ConvertToShoppingCartItems(HttpResponseMessage response)\n    {\n      response.EnsureSuccessStatusCode();\n      var products = \n        JsonConvert.DeserializeObject<List<ProductCatalogueProduct>>(await response.Content.ReadAsStringAsync().ConfigureAwait(false));\n      return\n        products\n          .Select(p => new ShoppingCartItem(\n            int.Parse(p.ProductId),\n            p.ProductName,\n            p.ProductDescription,\n            p.Price\n        ));\n    }\n\n    private class ProductCatalogueProduct\n    {\n      public string ProductId { get; set; }\n      public string ProductName { get; set; }\n      public string ProductDescription { get; set; }\n      public Money Price { get; set; }\n    }\n  }\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/Program.cs",
    "content": "using System.IO;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace ShoppingCart\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseUrls(\"http://localhost:5200\")\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"ShoppingCart\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/ShoppingCart/IShoppingCartStore.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using System.Threading.Tasks;\n  \n  public interface IShoppingCartStore\n  {\n    Task<ShoppingCart> Get(int userId);\n    Task Save(ShoppingCart shoppingCart);\n  }\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/ShoppingCart/ShoppingCart.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using System.Collections.Generic;\n  using System.Linq;\n  using global::ShoppingCart.EventFeed;\n\n  public class ShoppingCart\n  {\n    private HashSet<ShoppingCartItem> items = new HashSet<ShoppingCartItem>();\n\n    public int UserId { get; }\n    public IEnumerable<ShoppingCartItem> Items { get { return items; } }\n\n    public ShoppingCart(int userId)\n    {\n      this.UserId = userId;\n    }\n\n    public ShoppingCart(int userId, IEnumerable<ShoppingCartItem> items)\n    {\n      this.UserId = userId;\n      foreach (var item in items)\n      {\n        this.items.Add(item);  \n      }\n    }\n    \n    public void AddItems(\n      IEnumerable<ShoppingCartItem> shoppingCartItems,\n      IEventStore eventStore)\n    {\n      foreach (var item in shoppingCartItems)\n        if (this.items.Add(item))\n          eventStore.Raise(\n            \"ShoppingCartItemAdded\",\n            new { UserId, item });\n    }\n\n    public void RemoveItems(\n      int[] productCatalogueIds,\n      IEventStore eventStore)\n    {\n      items.RemoveWhere(i => productCatalogueIds.Contains(i.ProductCatalogueId));\n    }\n  }\n\n  public class ShoppingCartItem\n  {\n    public int ProductCatalogueId { get; }\n    public string ProductName { get; }\n    public string Desscription { get; }\n    public Money Price { get; }\n\n    public ShoppingCartItem(\n      int productCatalogueId,\n      string productName,\n      string description,\n      Money price)\n    {\n      this.ProductCatalogueId = productCatalogueId;\n      this.ProductName = productName;\n      this.Desscription = description;\n      this.Price = price;\n    }\n\n    public override bool Equals(object obj)\n    {\n      if (obj == null || GetType() != obj.GetType())\n      {\n        return false;\n      }\n\n      var that = obj as ShoppingCartItem;\n      return this.ProductCatalogueId.Equals(that.ProductCatalogueId);\n    }\n\n    // override object.GetHashCode\n    public override int GetHashCode()\n    {\n      return this.ProductCatalogueId.GetHashCode();\n    }\n  }\n\n  public class Money\n  {\n    public string Currency { get; }\n    public decimal Amount { get; }\n\n    public Money(string currency, decimal amount)\n    {\n      this.Currency = currency;\n      this.Amount = amount;\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/ShoppingCart/ShoppingCartModule.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n  using EventFeed;\n  using Nancy;\n  using Nancy.ModelBinding;\n\n  public class ShoppingCartModule : NancyModule\n  {\n    public ShoppingCartModule(\n      IShoppingCartStore shoppingCartStore,\n      IProductCatalogueClient productCatalogue,\n      IEventStore eventStore) \n      : base(\"/shoppingcart\")\n    {\n      Get(\"/{userid:int}\", parameters =>\n      {\n        var userId = (int) parameters.userid;\n        return shoppingCartStore.Get(userId);\n      });\n\n      Post(\"/{userid:int}/items\", async parameters =>\n      {\n        var productCatalogueIds = this.Bind<int[]>();\n        var userId = (int) parameters.userid;\n\n        var shoppingCart = await shoppingCartStore.Get(userId).ConfigureAwait(false);\n        var shoppingCartItems = await productCatalogue.GetShoppingCartItems(productCatalogueIds).ConfigureAwait(false);\n        shoppingCart.AddItems(shoppingCartItems, eventStore);\n        await shoppingCartStore.Save(shoppingCart);\n\n        return shoppingCart;\n      });\n\n      Delete(\"/{userid:int}/items\", async parameters =>\n      {\n        var productCatalogueIds = this.Bind<int[]>();\n        var userId = (int)parameters.userid;\n\n        var shoppingCart = await shoppingCartStore.Get(userId).ConfigureAwait(false);\n        shoppingCart.RemoveItems(productCatalogueIds, eventStore);\n        await shoppingCartStore.Save(shoppingCart);\n\n        return shoppingCart;\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/ShoppingCart/ShoppingCartStore.cs",
    "content": "﻿namespace ShoppingCart.ShoppingCart\n{\n    using System;\n    using System.Collections.Generic;\n    using System.Data.SqlClient;\n    using System.Threading.Tasks;\n    using Dapper;\n\n    public class ShoppingCartStore : IShoppingCartStore\n  {\n    private string connectionString =\n@\"Data Source=.\\SQLEXPRESS;Initial Catalog=ShoppingCart;\nIntegrated Security=True\";\n\n    private const string readItemsSql =\n@\"select * from ShoppingCart, ShoppingCartItems\nwhere ShoppingCartItems.ShoppingCartId = ID\nand ShoppingCart.UserId=@UserId\";\n\n    public async Task<ShoppingCart> Get(int userId)\n    {\n      using (var conn = new SqlConnection(connectionString))\n      {\n        var items = await\n          conn.QueryAsync<ShoppingCartItem>(\n            readItemsSql, \n            new { UserId = userId });\n        return new ShoppingCart(userId, items);\n      }\n    }\n\n      private const string deleteAllForShoppingCartSql=\n @\"delete item from ShoppingCartItems item\ninner join ShoppingCart cart on item.ShoppingCartId = cart.ID\nand cart.UserId=@UserId\";\n \n      private const string addAllForShoppingCartSql=\n@\"insert into ShoppingCartItems \n(ShoppingCartId, ProductCatalogId, ProductName, \nProductDescription, Amount, Currency)\nvalues \n(@ShoppingCartId, @ProductCatalogId, @ProductName,v\n@ProductDescription, @Amount, @Currency)\";\n\n    public async Task Save(ShoppingCart shoppingCart)\n    {\n      using (var conn = new SqlConnection(connectionString))\n      using (var tx = conn.BeginTransaction())\n      {\n        await conn.ExecuteAsync(\n          deleteAllForShoppingCartSql,\n          new { UserId = shoppingCart.UserId },\n          tx).ConfigureAwait(false);\n        await conn.ExecuteAsync(\n          addAllForShoppingCartSql,\n          shoppingCart.Items,\n          tx).ConfigureAwait(false);\n      }\n    }\n\n    }\n}"
  },
  {
    "path": "src/Chapter12/ShoppingCart/ShoppingCart.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>10e4f601-c16b-4936-a7b4-d32d799318d1</ProjectGuid>\n    <RootNamespace>ShoppingCart</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/Chapter12/ShoppingCart/Startup.cs",
    "content": "namespace ShoppingCart\n{\n    using Microsoft.AspNetCore.Builder;\n    using Nancy;\n    using Nancy.Configuration;\n    using Nancy.Owin;\n\n    public class Startup\n    {\n        public void Configure(IApplicationBuilder app)\n        {\n            app.UseOwin().UseNancy(opt => opt.Bootstrapper = new TracingBootstrapper());\n        }\n    }    \n    \n    public class TracingBootstrapper : Nancy.DefaultNancyBootstrapper\n    {\n        public override void Configure(INancyEnvironment env)\n        {\n            env.Tracing(enabled: true, displayErrorTraces: true);            \n        }\n    } \n}\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/database-scripts/create-shopping-cart-db.sql",
    "content": "CREATE DATABASE ShoppingCart\nGO\n\nUSE [ShoppingCart]\nGO\n\nCREATE TABLE [dbo].[ShoppingCart](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n  [UserId] [bigint] NOT NULL,\n  CONSTRAINT ShoppingCartUnique UNIQUE([ID], [UserID])\n)\nGO\n\nCREATE INDEX ShoppingCart_UserId \nON [dbo].[ShoppingCart] (UserId)\nGO\n\nCREATE TABLE [dbo].[ShoppingCartItems](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n\t[ShoppingCartId] [int] NOT NULL,\n\t[ProductCatalogId] [bigint] NOT NULL,\n\t[ProductName] [nvarchar](100) NOT NULL,\n\t[ProductDescription] [nvarchar](500) NULL,\n\t[Amount] [int] NOT NULL,\n\t[Currency] [nvarchar](5) NOT NULL\n)\n\nGO\n\nALTER TABLE [dbo].[ShoppingCartItems]  WITH CHECK ADD CONSTRAINT [FK_ShoppingCart] FOREIGN KEY([ShoppingCartId])\nREFERENCES [dbo].[ShoppingCart] ([Id])\nGO\n\nALTER TABLE [dbo].[ShoppingCartItems] CHECK CONSTRAINT [FK_ShoppingCart]\nGO\n\nCREATE INDEX ShoppingCartItems_ShoppingCartId \nON [dbo].[ShoppingCartItems] (ShoppingCartId)\nGO\n\nCREATE TABLE [dbo].[EventStore](\n  [ID] int IDENTITY(1,1) PRIMARY KEY,\n  [Name] [nvarchar](100)  NOT NULL,\n  [OccuredAt] [datetimeoffset] NOT NULL,\n  [Content][nvarchar](max) NOT NULL\n)\nGO\n\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"Polly\": \"4.2.1\",\n    \"Dapper\": \"1.50.0-rc2a\"\n  },\n  \"runtimes\": {\n    \"win10-x64\": \"\"\n  },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ],\n      \"dependencies\": {\n        \"System.Net.Http\": \"4.0.1\"\n      }\n    },\n    \"net461\": {\n      \"buildOptions\": {\"define\": [\"net461\"]},\n      \"frameworkAssemblies\": {\n        \"System.Net.Http\": \"4.0.0.0\",\n        \"System.Runtime\": \"4.0.20.0\"\n      },\n      \"dependencies\": {\n        \"EventStore.Client\": \"3.3.1\",\n        \"Microsoft.CSharp\": \"4.0.0\"\n      }\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"HelloMicroservices\"\n  }\n}\n"
  },
  {
    "path": "src/Chapter12/ShoppingCart/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/Chapter12/start-app.ps1",
    "content": "start-process dotnet -ArgumentList run -WorkingDirectory ./Login\nstart-process dotnet -ArgumentList run -WorkingDirectory ./ProductCatalog\nstart-process dotnet -ArgumentList run -WorkingDirectory ./ShoppingCart\nstart-process dotnet -ArgumentList run -WorkingDirectory ./ApiGateway"
  },
  {
    "path": "src/chapter08/OwinMiddlewareTests/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/chapter08/OwinMiddlewareTests/LibOwin.cs",
    "content": "﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.\n// Copyright (c) Damian Hickey. All rights reserved. See License.txt in the project root for license information.\n\n// https://github.com/damianh/LibOwin\n// Modifying this file may result in difficulties when upgrading the package.\n// All types are internal. Add a LIBOWIN_PUBLIC compilation symbol to make them public.\n\nnamespace LibOwin.Infrastructure\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Linq;\n\n    internal static partial class Constants\n    {\n        internal const string Https = \"HTTPS\";\n\n        internal const string HttpDateFormat = \"r\";\n\n        internal static partial class Headers\n        {\n            internal const string ContentType = \"Content-Type\";\n            internal const string CacheControl = \"Cache-Control\";\n            internal const string MediaType = \"Media-Type\";\n            internal const string Accept = \"Accept\";\n            internal const string Host = \"Host\";\n            internal const string ETag = \"ETag\";\n            internal const string Location = \"Location\";\n            internal const string ContentLength = \"Content-Length\";\n            internal const string SetCookie = \"Set-Cookie\";\n            internal const string Expires = \"Expires\";\n        }\n    }\n\n    internal struct HeaderSegment : IEquatable<HeaderSegment>\n    {\n        private readonly StringSegment _formatting;\n        private readonly StringSegment _data;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public HeaderSegment(StringSegment formatting, StringSegment data)\n        {\n            _formatting = formatting;\n            _data = data;\n        }\n\n        public StringSegment Formatting\n        {\n            get { return _formatting; }\n        }\n\n        public StringSegment Data\n        {\n            get { return _data; }\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegment other)\n        {\n            return _formatting.Equals(other._formatting) && _data.Equals(other._data);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegment && Equals((HeaderSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return (_formatting.GetHashCode() * 397) ^ _data.GetHashCode();\n            }\n        }\n\n        public static bool operator ==(HeaderSegment left, HeaderSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegment left, HeaderSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n    }\n\n    internal struct HeaderSegmentCollection : IEnumerable<HeaderSegment>, IEquatable<HeaderSegmentCollection>\n    {\n        private readonly string[] _headers;\n\n        public HeaderSegmentCollection(string[] headers)\n        {\n            _headers = headers;\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegmentCollection other)\n        {\n            return Equals(_headers, other._headers);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegmentCollection && Equals((HeaderSegmentCollection)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return (_headers != null ? _headers.GetHashCode() : 0);\n        }\n\n        public static bool operator ==(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public Enumerator GetEnumerator()\n        {\n            return new Enumerator(_headers);\n        }\n\n        IEnumerator<HeaderSegment> IEnumerable<HeaderSegment>.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        internal struct Enumerator : IEnumerator<HeaderSegment>\n        {\n            private readonly string[] _headers;\n            private int _index;\n\n            private string _header;\n            private int _headerLength;\n            private int _offset;\n\n            private int _leadingStart;\n            private int _leadingEnd;\n            private int _valueStart;\n            private int _valueEnd;\n            private int _trailingStart;\n\n            private Mode _mode;\n\n            private static readonly string[] NoHeaders = new string[0];\n\n            public Enumerator(string[] headers)\n            {\n                _headers = headers ?? NoHeaders;\n                _header = string.Empty;\n                _headerLength = -1;\n                _index = -1;\n                _offset = -1;\n                _leadingStart = -1;\n                _leadingEnd = -1;\n                _valueStart = -1;\n                _valueEnd = -1;\n                _trailingStart = -1;\n                _mode = Mode.Leading;\n            }\n\n            private enum Mode\n            {\n                Leading,\n                Value,\n                ValueQuoted,\n                Trailing,\n                Produce,\n            }\n\n            private enum Attr\n            {\n                Value,\n                Quote,\n                Delimiter,\n                Whitespace\n            }\n\n            public HeaderSegment Current\n            {\n                get\n                {\n                    return new HeaderSegment(\n                        new StringSegment(_header, _leadingStart, _leadingEnd - _leadingStart),\n                        new StringSegment(_header, _valueStart, _valueEnd - _valueStart));\n                }\n            }\n\n            object IEnumerator.Current\n            {\n                get { return Current; }\n            }\n\n            public void Dispose()\n            {\n            }\n\n            public bool MoveNext()\n            {\n                while (true)\n                {\n                    if (_mode == Mode.Produce)\n                    {\n                        _leadingStart = _trailingStart;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        if (_offset == _headerLength &&\n                            _leadingStart != -1 &&\n                            _leadingStart != _offset)\n                        {\n                            // Also produce trailing whitespace\n                            _leadingEnd = _offset;\n                            return true;\n                        }\n                        _mode = Mode.Leading;\n                    }\n\n                    // if end of a string\n                    if (_offset == _headerLength)\n                    {\n                        ++_index;\n                        _offset = -1;\n                        _leadingStart = 0;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        // if that was the last string\n                        if (_index == _headers.Length)\n                        {\n                            // no more move nexts\n                            return false;\n                        }\n\n                        // grab the next string\n                        _header = _headers[_index] ?? string.Empty;\n                        _headerLength = _header.Length;\n                    }\n                    while (true)\n                    {\n                        ++_offset;\n                        char ch = _offset == _headerLength ? (char)0 : _header[_offset];\n                        // todo - array of attrs\n                        Attr attr = char.IsWhiteSpace(ch) ? Attr.Whitespace : ch == '\\\"' ? Attr.Quote : (ch == ',' || ch == (char)0) ? Attr.Delimiter : Attr.Value;\n\n                        switch (_mode)\n                        {\n                            case Mode.Leading:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _leadingEnd = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Value:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Delimiter:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Value:\n                                        // more\n                                        break;\n                                    case Attr.Whitespace:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Trailing;\n                                        break;\n                                }\n                                break;\n                            case Mode.ValueQuoted:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Delimiter:\n                                        if (ch == (char)0)\n                                        {\n                                            _valueEnd = _offset;\n                                            _trailingStart = _offset;\n                                            _mode = Mode.Produce;\n                                        }\n                                        break;\n                                    case Attr.Value:\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Trailing:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                        }\n                        if (_mode == Mode.Produce)\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n\n            public void Reset()\n            {\n                _index = 0;\n                _offset = 0;\n                _leadingStart = 0;\n                _leadingEnd = 0;\n                _valueStart = 0;\n                _valueEnd = 0;\n            }\n        }\n    }\n\n    internal struct StringSegment : IEquatable<StringSegment>\n    {\n        private readonly string _buffer;\n        private readonly int _offset;\n        private readonly int _count;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public StringSegment(string buffer, int offset, int count)\n        {\n            _buffer = buffer;\n            _offset = offset;\n            _count = count;\n        }\n\n        public string Buffer\n        {\n            get { return _buffer; }\n        }\n\n        public int Offset\n        {\n            get { return _offset; }\n        }\n\n        public int Count\n        {\n            get { return _count; }\n        }\n\n        public string Value\n        {\n            get { return _offset == -1 ? null : _buffer.Substring(_offset, _count); }\n        }\n\n        public bool HasValue\n        {\n            get { return _offset != -1 && _count != 0 && _buffer != null; }\n        }\n\n        #region Equality members\n\n        public bool Equals(StringSegment other)\n        {\n            return string.Equals(_buffer, other._buffer) && _offset == other._offset && _count == other._count;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is StringSegment && Equals((StringSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hashCode = (_buffer != null ? _buffer.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ _offset;\n                hashCode = (hashCode * 397) ^ _count;\n                return hashCode;\n            }\n        }\n\n        public static bool operator ==(StringSegment left, StringSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(StringSegment left, StringSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public bool StartsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool EndsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset + _count - textLength, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool Equals(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count != textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public string Substring(int offset, int length)\n        {\n            return _buffer.Substring(_offset + offset, length);\n        }\n\n        public StringSegment Subsegment(int offset, int length)\n        {\n            return new StringSegment(_buffer, _offset + offset, length);\n        }\n\n        public override string ToString()\n        {\n            return Value ?? string.Empty;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AddCookieCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, string>)state;\n            if (!dictionary.ContainsKey(name))\n            {\n                dictionary.Add(name, value);\n            }\n        };\n\n        private static readonly char[] SemicolonAndComma = new[] { ';', ',' };\n\n        internal static IDictionary<string, string> GetCookies(IOwinRequest request)\n        {\n            var cookies = request.Get<IDictionary<string, string>>(\"Microsoft.Owin.Cookies#dictionary\");\n            if (cookies == null)\n            {\n                cookies = new Dictionary<string, string>(StringComparer.Ordinal);\n                request.Set(\"Microsoft.Owin.Cookies#dictionary\", cookies);\n            }\n\n            string text = GetHeader(request.Headers, \"Cookie\");\n            if (request.Get<string>(\"Microsoft.Owin.Cookies#text\") != text)\n            {\n                cookies.Clear();\n                ParseDelimited(text, SemicolonAndComma, AddCookieCallback, cookies);\n                request.Set(\"Microsoft.Owin.Cookies#text\", text);\n            }\n            return cookies;\n        }\n\n        internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)\n        {\n            int textLength = text.Length;\n            int equalIndex = text.IndexOf('=');\n            if (equalIndex == -1)\n            {\n                equalIndex = textLength;\n            }\n            int scanIndex = 0;\n            while (scanIndex < textLength)\n            {\n                int delimiterIndex = text.IndexOfAny(delimiters, scanIndex);\n                if (delimiterIndex == -1)\n                {\n                    delimiterIndex = textLength;\n                }\n                if (equalIndex < delimiterIndex)\n                {\n                    while (scanIndex != equalIndex && char.IsWhiteSpace(text[scanIndex]))\n                    {\n                        ++scanIndex;\n                    }\n                    string name = text.Substring(scanIndex, equalIndex - scanIndex);\n                    string value = text.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);\n                    callback(\n                        Uri.UnescapeDataString(name.Replace('+', ' ')),\n                        Uri.UnescapeDataString(value.Replace('+', ' ')),\n                        state);\n                    equalIndex = text.IndexOf('=', delimiterIndex);\n                    if (equalIndex == -1)\n                    {\n                        equalIndex = textLength;\n                    }\n                }\n                scanIndex = delimiterIndex + 1;\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        public static string GetHeader(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        public static IEnumerable<string> GetHeaderSplit(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : GetHeaderSplitImplementation(values);\n        }\n\n        private static IEnumerable<string> GetHeaderSplitImplementation(string[] values)\n        {\n            foreach (var segment in new HeaderSegmentCollection(values))\n            {\n                if (segment.Data.HasValue)\n                {\n                    yield return DeQuote(segment.Data.Value);\n                }\n            }\n        }\n\n        public static string[] GetHeaderUnmodified(IDictionary<string, string[]> headers, string key)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            string[] values;\n            return headers.TryGetValue(key, out values) ? values : null;\n        }\n\n        public static void SetHeader(IDictionary<string, string[]> headers, string key, string value)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { value };\n            }\n        }\n\n        public static void SetHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        // Quote items that contain comas and are not already quoted.\n        private static string QuoteIfNeeded(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Contains(','))\n            {\n                if (value[0] != '\"' || value[value.Length - 1] != '\"')\n                {\n                    value = '\"' + value + '\"';\n                }\n            }\n\n            return value;\n        }\n\n        private static string DeQuote(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Length > 1 && value[0] == '\"' && value[value.Length - 1] == '\"')\n            {\n                value = value.Substring(1, value.Length - 2);\n            }\n\n            return value;\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = values;\n            }\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, IEnumerable<string> values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            headers[key] = values.ToArray();\n        }\n\n        public static void AppendHeader(IDictionary<string, string[]> headers, string key, string values)\n        {\n            if (string.IsNullOrWhiteSpace(values))\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeader(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + values };\n            }\n        }\n\n        public static void AppendHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeaderJoined(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        public static void AppendHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string[] existing = GetHeaderUnmodified(headers, key);\n            if (existing == null)\n            {\n                SetHeaderUnmodified(headers, key, values);\n            }\n            else\n            {\n                SetHeaderUnmodified(headers, key, existing.Concat(values));\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AppendItemCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, List<String>>)state;\n\n            List<string> existing;\n            if (!dictionary.TryGetValue(name, out existing))\n            {\n                dictionary.Add(name, new List<string>(1) { value });\n            }\n            else\n            {\n                existing.Add(value);\n            }\n        };\n\n        private static readonly char[] AmpersandAndSemicolon = new[] { '&', ';' };\n\n        internal static IDictionary<string, string[]> GetQuery(IOwinRequest request)\n        {\n            var query = request.Get<IDictionary<string, string[]>>(\"Microsoft.Owin.Query#dictionary\");\n            if (query == null)\n            {\n                query = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n                request.Set(\"Microsoft.Owin.Query#dictionary\", query);\n            }\n\n            string text = request.QueryString.Value;\n            if (request.Get<string>(\"Microsoft.Owin.Query#text\") != text)\n            {\n                query.Clear();\n                var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n                ParseDelimited(text, AmpersandAndSemicolon, AppendItemCallback, accumulator);\n                foreach (var kv in accumulator)\n                {\n                    query.Add(kv.Key, kv.Value.ToArray());\n                }\n                request.Set(\"Microsoft.Owin.Query#text\", text);\n            }\n            return query;\n        }\n\n        internal static IFormCollection GetForm(string text)\n        {\n            IDictionary<string, string[]> form = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n            ParseDelimited(text, new[] { '&' }, AppendItemCallback, accumulator);\n            foreach (var kv in accumulator)\n            {\n                form.Add(kv.Key, kv.Value.ToArray());\n            }\n            return new FormCollection(form);\n        }\n\n        internal static string GetJoinedValue(IDictionary<string, string[]> store, string key)\n        {\n            string[] values = GetUnmodifiedValues(store, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        internal static string[] GetUnmodifiedValues(IDictionary<string, string[]> store, string key)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n            string[] values;\n            return store.TryGetValue(key, out values) ? values : null;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        internal static string GetHost(IOwinRequest request)\n        {\n            IHeaderDictionary headers = request.Headers;\n\n            string host = GetHeader(headers, \"Host\");\n            if (!string.IsNullOrWhiteSpace(host))\n            {\n                return host;\n            }\n\n            string localIpAddress = request.LocalIpAddress ?? \"localhost\";\n            var localPort = request.Get<string>(OwinConstants.CommonKeys.LocalPort);\n            return string.IsNullOrWhiteSpace(localPort) ? localIpAddress : (localIpAddress + \":\" + localPort);\n        }\n    }\n}\n\nnamespace LibOwin\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Globalization;\n    using System.IO;\n    using System.Linq;\n    using System.Security.Claims;\n    using System.Security.Principal;\n    using System.Text;\n    using System.Threading;\n    using System.Threading.Tasks;\n    using LibOwin.Infrastructure;\n\n    #if LIBOWIN_PUBLIC\n\n    public partial class CookieOptions { }\n    public partial class FormCollection { }\n    public partial class HeaderDictionary { }\n    public partial struct HostString { }\n    public partial interface IFormCollection { }\n    public partial interface IHeaderDictionary { }\n    public partial interface IOwinContext { }\n    public partial interface IOwinRequest { }\n    public partial interface IOwinResponse { }\n    public partial interface IReadableStringCollection { }\n    public partial class OwinContext { }\n    public partial class OwinRequest { }\n    public partial class OwinResponse { }\n    public partial struct PathString { }\n    public partial struct QueryString { }\n    public partial class ReadableStringCollection { }\n    public partial class RequestCookieCollection { }\n    public partial class ResponseCookieCollection { }\n    public partial class IOwinResponseExtension { }\n\n    #endif\n\n    /// <summary>\n    /// Options used to create a new cookie.\n    /// </summary>\n    partial class CookieOptions\n    {\n        /// <summary>\n        /// Creates a default cookie with a path of '/'.\n        /// </summary>\n        public CookieOptions()\n        {\n            Path = \"/\";\n        }\n\n        /// <summary>\n        /// Gets or sets the domain to associate the cookie with.\n        /// </summary>\n        /// <returns>The domain to associate the cookie with.</returns>\n        public string Domain { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cookie path.\n        /// </summary>\n        /// <returns>The cookie path.</returns>\n        public string Path { get; set; }\n\n        /// <summary>\n        /// Gets or sets the expiration date and time for the cookie.\n        /// </summary>\n        /// <returns>The expiration date and time for the cookie.</returns>\n        public DateTime? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether to transmit the cookie using Secure Sockets Layer (SSL)—that is, over HTTPS only.\n        /// </summary>\n        /// <returns>true to transmit the cookie only over an SSL connection (HTTPS); otherwise, false.</returns>\n        public bool Secure { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether a cookie is accessible by client-side script.\n        /// </summary>\n        /// <returns>true if a cookie is accessible by client-side script; otherwise, false.</returns>\n        public bool HttpOnly { get; set; }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial class FormCollection : ReadableStringCollection, IFormCollection\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.FormCollection\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The store for the form.</param>\n        public FormCollection(IDictionary<string, string[]> store)\n            : base(store)\n        {}\n    }\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial class HeaderDictionary : IHeaderDictionary\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The underlying data store.</param>\n        public HeaderDictionary(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Gets an <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public ICollection<string> Keys\n        {\n            get { return Store.Keys; }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        public ICollection<string[]> Values\n        {\n            get { return Store.Values; }\n        }\n\n        /// <summary>\n        /// Gets the number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>The number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public int Count\n        {\n            get { return Store.Count; }\n        }\n\n        /// <summary>\n        /// Gets a value that indicates whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode.\n        /// </summary>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode; otherwise, false.</returns>\n        public bool IsReadOnly\n        {\n            get { return Store.IsReadOnly; }\n        }\n\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n            set { Set(key, value); }\n        }\n\n        /// <summary>\n        /// Throws KeyNotFoundException if the key is not present.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns></returns>\n        string[] IDictionary<string, string[]>.this[string key]\n        {\n            get { return Store[key]; }\n            set { Store[key] = value; }\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetHeader(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection without modification, or null if the key is not present.</returns>\n        public IList<string> GetValues(string key)\n        {\n            return OwinHelpers.GetHeaderUnmodified(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        public IList<string> GetCommaSeparatedValues(string key)\n        {\n            IEnumerable<string> values = OwinHelpers.GetHeaderSplit(Store, key);\n            return values == null ? null : values.ToList();\n        }\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Append(string key, string value)\n        {\n            OwinHelpers.AppendHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Set(string key, string value)\n        {\n            OwinHelpers.SetHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Adds the given header and values to the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header values.</param>\n        public void Add(string key, string[] value)\n        {\n            Store.Add(key, value);\n        }\n\n        /// <summary>\n        /// Determines whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key.\n        /// </summary>\n        /// <param name=\"key\">The key.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key; otherwise, false.</returns>\n        public bool ContainsKey(string key)\n        {\n            return Store.ContainsKey(key);\n        }\n\n        /// <summary>\n        /// Removes the given header from the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(string key)\n        {\n            return Store.Remove(key);\n        }\n\n        /// <summary>\n        /// Retrieves a value from the dictionary.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The value.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains the key; otherwise, false.</returns>\n        public bool TryGetValue(string key, out string[] value)\n        {\n            return Store.TryGetValue(key, out value);\n        }\n\n        /// <summary>\n        /// Adds a new list of items to the collection.\n        /// </summary>\n        /// <param name=\"item\">The item to add.</param>\n        public void Add(KeyValuePair<string, string[]> item)\n        {\n            Store.Add(item);\n        }\n\n        /// <summary>\n        /// Clears the entire list of objects.\n        /// </summary>\n        public void Clear()\n        {\n            Store.Clear();\n        }\n\n        /// <summary>\n        /// Returns a value indicating whether the specified object occurs within this collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object occurs within this collection; otherwise, false.</returns>\n        public bool Contains(KeyValuePair<string, string[]> item)\n        {\n            return Store.Contains(item);\n        }\n\n        /// <summary>\n        /// Copies the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> elements to a one-dimensional Array instance at the specified index.\n        /// </summary>\n        /// <param name=\"array\">The one-dimensional Array that is the destination of the specified objects copied from the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</param>\n        /// <param name=\"arrayIndex\">The zero-based index in <paramref name=\"array\" /> at which copying begins.</param>\n        public void CopyTo(KeyValuePair<string, string[]>[] array, int arrayIndex)\n        {\n            Store.CopyTo(array, arrayIndex);\n        }\n\n        /// <summary>\n        /// Removes the given item from the the collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(KeyValuePair<string, string[]> item)\n        {\n            return Store.Remove(item);\n        }\n    }\n\n    /// <summary>\n    /// Represents the host portion of a Uri can be used to construct Uri's properly formatted and encoded for use in\n    /// HTTP headers.\n    /// </summary>\n    partial struct HostString : IEquatable<HostString>\n    {\n        private readonly string _value;\n\n        /// <summary>\n        /// Creates a new HostString without modification. The value should be Unicode rather than punycode, and may have a port.\n        /// IPv4 and IPv6 addresses are also allowed, and also may have ports.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        public HostString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Returns the original value from the constructor.\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// Returns the value as normalized by ToUriComponent().\n        /// </summary>\n        /// <returns></returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Returns the value properly formatted and encoded for use in a URI in a HTTP header.\n        /// Any Unicode is converted to punycode. IPv6 addresses will have brackets added if they are missing.\n        /// </summary>\n        /// <returns></returns>\n        public string ToUriComponent()\n        {\n            int index;\n            if (string.IsNullOrEmpty(_value))\n            {\n                return string.Empty;\n            }\n            else if (_value.IndexOf('[') >= 0)\n            {\n                // IPv6 in brackets [::1], maybe with port\n                return _value;\n            }\n            else if ((index = _value.IndexOf(':')) >= 0\n                && index < _value.Length - 1\n                && _value.IndexOf(':', index + 1) >= 0)\n            {\n                // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                return \"[\" + _value + \"]\";\n            }\n            else if (index >= 0)\n            {\n                // Has a port\n                string port = _value.Substring(index);\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value, 0, index) + port;\n            }\n            else\n            {\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value);\n            }\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the given uri component.\n        /// Any punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uriComponent\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(string uriComponent)\n        {\n            if (!string.IsNullOrEmpty(uriComponent))\n            {\n                int index;\n                if (uriComponent.IndexOf('[') >= 0)\n                {\n                    // IPv6 in brackets [::1], maybe with port\n                }\n                else if ((index = uriComponent.IndexOf(':')) >= 0\n                    && index < uriComponent.Length - 1\n                    && uriComponent.IndexOf(':', index + 1) >= 0)\n                {\n                    // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                }\n                else if (uriComponent.IndexOf(\"xn--\", StringComparison.Ordinal) >= 0)\n                {\n                    // Contains punycode\n                    if (index >= 0)\n                    {\n                        // Has a port\n                        string port = uriComponent.Substring(index);\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent, 0, index) + port;\n                    }\n                    else\n                    {\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent);\n                    }\n                }\n            }\n            return new HostString(uriComponent);\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the host and port of the give Uri instance.\n        /// Punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uri\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new HostString(uri.GetComponents(\n                UriComponents.NormalizedHost | // Always convert punycode to Unicode.\n                UriComponents.HostAndPort, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Compares the equality of the Value property, ignoring case.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(HostString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares against the given object only if it is a HostString.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is HostString && Equals((HostString)obj);\n        }\n\n        /// <summary>\n        /// Gets a hash code for the value.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(HostString left, HostString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(HostString left, HostString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial interface IFormCollection : IReadableStringCollection\n    {}\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, string[]>\n    {\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        new string this[string key] { get; set; }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        IList<string> GetCommaSeparatedValues(string key);\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Append(string key, string value);\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendCommaSeparatedValues(string key, params string[] values);\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Set(string key, string value);\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetCommaSeparatedValues(string key, params string[] values);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinContext\n    {\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        IOwinRequest Request { get; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        IOwinResponse Response { get; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        TextWriter TraceOutput { get; set; }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinContext Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinRequest\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        string Method { get; set; }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        string Scheme { get; set; }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        bool IsSecure { get; }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        HostString Host { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        PathString PathBase { get; set; }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        PathString Path { get; set; }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        QueryString QueryString { get; set; }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        IReadableStringCollection Query { get; }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        Uri Uri { get; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        RequestCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        string CacheControl { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        string MediaType { get; set; }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        string Accept { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        CancellationToken CallCancelled { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        string LocalIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        int? LocalPort { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        string RemoteIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        int? RemotePort { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        ClaimsPrincipal User { get; set; }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        Task<IFormCollection> ReadFormAsync();\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinRequest Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinResponse\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        int StatusCode { get; set; }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        string ReasonPhrase { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        ResponseCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        long? ContentLength { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        DateTimeOffset? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        string ETag { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        void OnSendingHeaders(Action<object> callback, object state);\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        void Redirect(string location);\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        void Write(string text);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        void Write(byte[] data);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        void Write(byte[] data, int offset, int count);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, int offset, int count, CancellationToken token);\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinResponse Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// Accessors for headers, query, forms, etc.\n    /// </summary>\n    partial interface IReadableStringCollection : IEnumerable<KeyValuePair<string, string[]>>\n    {\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string this[string key] { get; }\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string Get(string key);\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        IList<string> GetValues(string key);\n\n        // Raw\n    }\n\n    internal static class OwinConstants\n    {\n        #region OWIN v1.0.0 - 3.2.1. Request Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string RequestScheme = \"owin.RequestScheme\";\n        public const string RequestMethod = \"owin.RequestMethod\";\n        public const string RequestPathBase = \"owin.RequestPathBase\";\n        public const string RequestPath = \"owin.RequestPath\";\n        public const string RequestQueryString = \"owin.RequestQueryString\";\n        public const string RequestProtocol = \"owin.RequestProtocol\";\n        public const string RequestHeaders = \"owin.RequestHeaders\";\n        public const string RequestBody = \"owin.RequestBody\";\n        public const string RequestUser = \"owin.RequestUser\"; //owin 1.0.1\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.2. Response Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string ResponseStatusCode = \"owin.ResponseStatusCode\";\n        public const string ResponseReasonPhrase = \"owin.ResponseReasonPhrase\";\n        public const string ResponseProtocol = \"owin.ResponseProtocol\";\n        public const string ResponseHeaders = \"owin.ResponseHeaders\";\n        public const string ResponseBody = \"owin.ResponseBody\";\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.3. Other Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string CallCancelled = \"owin.CallCancelled\";\n\n        public const string OwinVersion = \"owin.Version\";\n\n        #endregion\n\n        #region OWIN Keys for IAppBuilder.Properties\n\n        internal static class Builder\n        {\n            public const string AddSignatureConversion = \"builder.AddSignatureConversion\";\n            public const string DefaultApp = \"builder.DefaultApp\";\n        }\n\n        #endregion\n\n        #region OWIN Key Guidelines and Common Keys - 6. Common keys\n\n        // http://owin.org/spec/CommonKeys.html\n\n        internal static class CommonKeys\n        {\n            public const string ClientCertificate = \"ssl.ClientCertificate\";\n            public const string RemoteIpAddress = \"server.RemoteIpAddress\";\n            public const string RemotePort = \"server.RemotePort\";\n            public const string LocalIpAddress = \"server.LocalIpAddress\";\n            public const string LocalPort = \"server.LocalPort\";\n            public const string IsLocal = \"server.IsLocal\";\n            public const string TraceOutput = \"host.TraceOutput\";\n            public const string Addresses = \"host.Addresses\";\n            public const string AppName = \"host.AppName\";\n            public const string Capabilities = \"server.Capabilities\";\n            public const string OnSendingHeaders = \"server.OnSendingHeaders\";\n            public const string OnAppDisposing = \"host.OnAppDisposing\";\n            public const string Scheme = \"scheme\";\n            public const string Host = \"host\";\n            public const string Port = \"port\";\n            public const string Path = \"path\";\n        }\n\n        #endregion\n\n        #region SendFiles v0.3.0\n\n        // http://owin.org/extensions/owin-SendFile-Extension-v0.3.0.htm\n\n        internal static class SendFiles\n        {\n            // 3.1. Startup\n\n            public const string Version = \"sendfile.Version\";\n            public const string Support = \"sendfile.Support\";\n            public const string Concurrency = \"sendfile.Concurrency\";\n\n            // 3.2. Per Request\n\n            public const string SendAsync = \"sendfile.SendAsync\";\n        }\n\n        #endregion\n\n        #region Opaque v0.3.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class OpaqueConstants\n        {\n            // 3.1. Startup\n            public const string Version = \"opaque.Version\";\n\n            // 3.2. Per Request\n            public const string Upgrade = \"opaque.Upgrade\";\n\n            // 5. Consumption\n            public const string Stream = \"opaque.Stream\";\n            // public const string Version = \"opaque.Version\"; // redundant, declared above\n            public const string CallCancelled = \"opaque.CallCancelled\";\n        }\n\n        #endregion\n\n        #region WebSocket v0.4.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class WebSocket\n        {\n            // 3.1. Startup\n            public const string Version = \"websocket.Version\";\n\n            // 3.2. Per Request\n            public const string Accept = \"websocket.Accept\";\n\n            // 4. Accept\n            public const string SubProtocol = \"websocket.SubProtocol\";\n\n            // 5. Consumption\n            public const string SendAsync = \"websocket.SendAsync\";\n            public const string ReceiveAsync = \"websocket.ReceiveAsync\";\n            public const string CloseAsync = \"websocket.CloseAsync\";\n            // public const string Version = \"websocket.Version\"; // redundant, declared above\n            public const string CallCancelled = \"websocket.CallCancelled\";\n            public const string ClientCloseStatus = \"websocket.ClientCloseStatus\";\n            public const string ClientCloseDescription = \"websocket.ClientCloseDescription\";\n        }\n\n        #endregion\n\n        #region Security v0.1.0\n\n        // http://owin.org/extensions/owin-Security-Extension-v0.1.0.htm\n\n        internal static class Security\n        {\n            // 3.2. Per Request\n\n            public const string User = \"server.User\";\n\n            public const string Authenticate = \"security.Authenticate\";\n\n            // 3.3. Response\n\n            public const string SignIn = \"security.SignIn\";\n\n            public const string SignOut = \"security.SignOut\";\n\n            public const string SignOutProperties = \"security.SignOutProperties\";\n\n            public const string Challenge = \"security.Challenge\";\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinContext : IOwinContext\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinContext()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Create a new wrapper.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinContext(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        public virtual IOwinRequest Request { get; private set; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        public virtual IOwinResponse Response { get; private set; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        public virtual TextWriter TraceOutput\n        {\n            get { return Get<TextWriter>(OwinConstants.CommonKeys.TraceOutput); }\n            set { Set<TextWriter>(OwinConstants.CommonKeys.TraceOutput, value); }\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinContext Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinRequest : IOwinRequest\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinRequest()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Create a new environment wrapper exposing request properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinRequest(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        public virtual string Method\n        {\n            get { return Get<string>(OwinConstants.RequestMethod); }\n            set { Set(OwinConstants.RequestMethod, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        public virtual string Scheme\n        {\n            get { return Get<string>(OwinConstants.RequestScheme); }\n            set { Set(OwinConstants.RequestScheme, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        public virtual bool IsSecure\n        {\n            get { return string.Equals(Scheme, Constants.Https, StringComparison.OrdinalIgnoreCase); }\n        }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        public virtual HostString Host\n        {\n            get { return new HostString(OwinHelpers.GetHost(this)); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Host, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        public virtual PathString PathBase\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPathBase)); }\n            set { Set(OwinConstants.RequestPathBase, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        public virtual PathString Path\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPath)); }\n            set { Set(OwinConstants.RequestPath, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        public virtual QueryString QueryString\n        {\n            get { return new QueryString(Get<string>(OwinConstants.RequestQueryString)); }\n            set { Set(OwinConstants.RequestQueryString, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        public virtual IReadableStringCollection Query\n        {\n            get { return new ReadableStringCollection(OwinHelpers.GetQuery(this)); }\n        }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        public virtual Uri Uri\n        {\n            get { return new Uri(Scheme + \"//\" + Host + PathBase + Path + QueryString); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.RequestProtocol); }\n            set { Set(OwinConstants.RequestProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.RequestHeaders); }\n        }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        public RequestCookieCollection Cookies\n        {\n            get { return new RequestCookieCollection(OwinHelpers.GetCookies(this)); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        public virtual string CacheControl\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.CacheControl); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.CacheControl, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        public virtual string MediaType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.MediaType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.MediaType, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        public virtual string Accept\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Accept); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Accept, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.RequestBody); }\n            set { Set(OwinConstants.RequestBody, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        public virtual CancellationToken CallCancelled\n        {\n            get { return Get<CancellationToken>(OwinConstants.CallCancelled); }\n            set { Set(OwinConstants.CallCancelled, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        public virtual string LocalIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalIpAddress); }\n            set { Set(OwinConstants.CommonKeys.LocalIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        public virtual int? LocalPort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(LocalPortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    LocalPortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.LocalPort);\n                }\n            }\n        }\n\n        private string LocalPortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalPort); }\n            set { Set(OwinConstants.CommonKeys.LocalPort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        public virtual string RemoteIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemoteIpAddress); }\n            set { Set(OwinConstants.CommonKeys.RemoteIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        public virtual int? RemotePort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(RemotePortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    RemotePortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.RemotePort);\n                }\n            }\n        }\n\n        private string RemotePortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemotePort); }\n            set { Set(OwinConstants.CommonKeys.RemotePort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        public virtual ClaimsPrincipal User\n        {\n            get\n            {\n                var claimsPrincipal = Get<ClaimsPrincipal>(OwinConstants.RequestUser);\n                return claimsPrincipal ?? Get<IPrincipal>(OwinConstants.Security.User) as ClaimsPrincipal;\n            }\n            set { Set(OwinConstants.RequestUser, value); }\n        }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        public async Task<IFormCollection> ReadFormAsync()\n        {\n            var form = Get<IFormCollection>(\"Microsoft.Owin.Form#collection\");\n            if (form == null)\n            {\n                string text;\n                // Don't close, it prevents re-winding.\n                using (var reader = new StreamReader(Body, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4 * 1024, leaveOpen: true))\n                {\n                    text = await reader.ReadToEndAsync();\n                }\n                form = OwinHelpers.GetForm(text);\n                Set(\"Microsoft.Owin.Form#collection\", form);\n            }\n\n            return form;\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinRequest Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinResponse : IOwinResponse\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinResponse()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Creates a new environment wrapper exposing response properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinResponse(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        public virtual int StatusCode\n        {\n            get { return Get<int>(OwinConstants.ResponseStatusCode, 200); }\n            set { Set(OwinConstants.ResponseStatusCode, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        public virtual string ReasonPhrase\n        {\n            get { return Get<string>(OwinConstants.ResponseReasonPhrase); }\n            set { Set(OwinConstants.ResponseReasonPhrase, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.ResponseProtocol); }\n            set { Set(OwinConstants.ResponseProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders); }\n        }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        public virtual ResponseCookieCollection Cookies\n        {\n            get { return new ResponseCookieCollection(Headers); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        public virtual long? ContentLength\n        {\n            get\n            {\n                long value;\n                if (long.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentLength), out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentLength,\n                        value.Value.ToString(CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.ContentLength);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        public virtual DateTimeOffset? Expires\n        {\n            get\n            {\n                DateTimeOffset value;\n                if (DateTimeOffset.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Expires),\n                    CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Expires,\n                        value.Value.ToString(Constants.HttpDateFormat, CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.Expires);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        public virtual string ETag\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ETag); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ETag, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.ResponseBody); }\n            set { Set(OwinConstants.ResponseBody, value); }\n        }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public virtual void OnSendingHeaders(Action<object> callback, object state)\n        {\n            var onSendingHeaders = Get<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);\n            if (onSendingHeaders == null)\n            {\n                throw new NotSupportedException(Resources.Exception_MissingOnSendingHeaders);\n            }\n            onSendingHeaders(callback, state);\n        }\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        public virtual void Redirect(string location)\n        {\n            StatusCode = 302;\n            OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Location, location);\n        }\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        public virtual void Write(string text)\n        {\n            Write(Encoding.UTF8.GetBytes(text));\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        public virtual void Write(byte[] data)\n        {\n            Write(data, 0, data == null ? 0 : data.Length);\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        public virtual void Write(byte[] data, int offset, int count)\n        {\n            Body.Write(data, offset, count);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text)\n        {\n            return WriteAsync(text, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text, CancellationToken token)\n        {\n            return WriteAsync(Encoding.UTF8.GetBytes(text), token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data)\n        {\n            return WriteAsync(data, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, CancellationToken token)\n        {\n            return WriteAsync(data, 0, data == null ? 0 : data.Length, token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, int offset, int count, CancellationToken token)\n        {\n            return Body.WriteAsync(data, offset, count, token);\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            return Get(key, default(T));\n        }\n\n        private T Get<T>(string key, T fallback)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : fallback;\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinResponse Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct PathString : IEquatable<PathString>\n    {\n        private static readonly Func<string, string> EscapeDataString = Uri.EscapeDataString;\n\n        /// <summary>\n        /// Represents the empty path. This field is read-only.\n        /// </summary>\n        public static readonly PathString Empty = new PathString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initialize the path string with a given value. This value must be in un-escaped format. Use\n        /// PathString.FromUriComponent(value) if you have a path value which is in an escaped format.\n        /// </summary>\n        /// <param name=\"value\">The unescaped path to be assigned to the Value property.</param>\n        public PathString(string value)\n        {\n            if (!String.IsNullOrEmpty(value) && value[0] != '/')\n            {\n                throw new ArgumentException(Resources.Exception_PathMustStartWithSlash, \"value\");\n            }\n            _value = value;\n        }\n\n        /// <summary>\n        /// The unescaped path value\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the path is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrEmpty(_value); }\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public string ToUriComponent()\n        {\n            if (HasValue)\n            {\n                if (RequiresEscaping(_value))\n                {\n                    // TODO: Measure the cost of this escaping and consider optimizing.\n                    return String.Join(\"/\", _value.Split('/').Select(EscapeDataString));\n                }\n                return _value;\n            }\n            return String.Empty;\n        }\n\n        // Very conservative, these characters do not need to be escaped in a path.\n        private static bool RequiresEscaping(string value)\n        {\n            for (int i = 0; i < value.Length; i++)\n            {\n                char c = value[i];\n                // Check conservatively for safe characters. See http://www.ietf.org/rfc/rfc3986.txt\n                bool safeChar =\n                    (('a' <= c && c <= 'z')\n                    || ('A' <= c && c <= 'Z')\n                    || ('0' <= c && c <= '9')\n                    || c == '/' || c == '-' || c == '_');\n                if (!safeChar)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a path.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped path as it appears in the URI format.</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(string uriComponent)\n        {\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(Uri.UnescapeDataString(uriComponent));\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(\"/\" + uri.GetComponents(UriComponents.Path, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                return value1.Length == value2.Length || value1[value2.Length] == '/';\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <param name=\"remaining\">Any remaining segments from this instance not included in the other instance.</param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other, out PathString remaining)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                if (value1.Length == value2.Length || value1[value2.Length] == '/')\n                {\n                    remaining = new PathString(value1.Substring(value2.Length));\n                    return true;\n                }\n            }\n            remaining = Empty;\n            return false;\n        }\n\n        /// <summary>\n        /// Adds two PathString instances into a combined PathString value.\n        /// </summary>\n        /// <returns>The combined PathString value</returns>\n        public PathString Add(PathString other)\n        {\n            return new PathString(Value + other.Value);\n        }\n\n        /// <summary>\n        /// Combines a PathString and QueryString into the joined URI formatted string value.\n        /// </summary>\n        /// <returns>The joined URI formatted string value</returns>\n        public string Add(QueryString other)\n        {\n            return ToUriComponent() + other.ToUriComponent();\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value using a specific StringComparison type\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison</param>\n        /// <param name=\"comparisonType\">The StringComparison type to use</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other, StringComparison comparisonType)\n        {\n            return string.Equals(_value, other._value, comparisonType);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"obj\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is PathString && Equals((PathString)obj, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation.\n        /// </summary>\n        /// <returns>The hash code</returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public static bool operator ==(PathString left, PathString right)\n        {\n            return left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are not equal</returns>\n        public static bool operator !=(PathString left, PathString right)\n        {\n            return !left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static PathString operator +(PathString left, PathString right)\n        {\n            return left.Add(right);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static string operator +(PathString left, QueryString right)\n        {\n            return left.Add(right);\n        }\n    }\n\n    /// <summary>\n    /// Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct QueryString : IEquatable<QueryString>\n    {\n        /// <summary>\n        /// Represents the empty query string. This field is read-only.\n        /// </summary>\n        public static readonly QueryString Empty = new QueryString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initalize the query string with a given value. This value must be in escaped and delimited format without\n        /// a leading '?' character.\n        /// </summary>\n        /// <param name=\"value\">The query string to be assigned to the Value property.</param>\n        public QueryString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Initialize a query string with a single given parameter name and value. The value is\n        /// </summary>\n        /// <param name=\"name\">The unencoded parameter name</param>\n        /// <param name=\"value\">The unencoded parameter value</param>\n        public QueryString(string name, string value)\n        {\n            _value = Uri.EscapeDataString(name) + '=' + Uri.EscapeDataString(value);\n        }\n\n        /// <summary>\n        /// The unescaped query string without the leading '?' character\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the query string is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrWhiteSpace(_value); }\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentally\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public string ToUriComponent()\n        {\n            // Escape things properly so System.Uri doesn't mis-interpret the data.\n            return HasValue ? \"?\" + _value.Replace(\"#\", \"%23\") : String.Empty;\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a query.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped query as it appears in the URI format.</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(string uriComponent)\n        {\n            if (String.IsNullOrEmpty(uriComponent))\n            {\n                return new QueryString(string.Empty);\n            }\n            if (uriComponent[0] != '?')\n            {\n                throw new ArgumentException(Resources.Exception_QueryStringMustStartWithDelimiter, \"uriComponent\");\n            }\n            return new QueryString(uriComponent.Substring(1));\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new QueryString(uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped));\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(QueryString other)\n        {\n            return string.Equals(_value, other._value);\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is QueryString && Equals((QueryString)obj);\n        }\n\n        /// <summary>\n        /// Returns the hash code for this instance.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? _value.GetHashCode() : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(QueryString left, QueryString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(QueryString left, QueryString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Accessors for query, forms, etc.\n    /// </summary>\n    partial class ReadableStringCollection : IReadableStringCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public ReadableStringCollection(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetJoinedValue(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public IList<string> GetValues(string key)\n        {\n            string[] values;\n            Store.TryGetValue(key, out values);\n            return values;\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    /// <summary>\n    /// A wrapper for the request Cookie header\n    /// </summary>\n    partial class RequestCookieCollection : IEnumerable<KeyValuePair<string, string>>\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public RequestCookieCollection(IDictionary<string, string> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string> Store { get; set; }\n\n        /// <summary>\n        /// Returns null rather than throwing KeyNotFoundException\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get\n            {\n                string value;\n                Store.TryGetValue(key, out value);\n                return value;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    internal static class Resources\n    {\n        internal const string Exception_MissingOnSendingHeaders = \"The OWIN key 'server.OnSsoendingHeaders' is not available for this request.\";\n        internal const string Exception_PathMustStartWithSlash = \"The path must start with a '/' followed by one or more characters.\";\n        internal const string Exception_QueryStringMustStartWithDelimiter = \"The query string must start with a '?' unless null or empty.\";\n    }\n\n    /// <summary>\n    /// A wrapper for the response Set-Cookie header\n    /// </summary>\n    partial class ResponseCookieCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"headers\"></param>\n        public ResponseCookieCollection(IHeaderDictionary headers)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n\n            Headers = headers;\n        }\n\n        private IHeaderDictionary Headers { get; set; }\n\n        /// <summary>\n        /// Add a new cookie and value\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        public void Append(string key, string value)\n        {\n            Headers.AppendValues(Constants.Headers.SetCookie, Uri.EscapeDataString(key) + \"=\" + Uri.EscapeDataString(value) + \"; path=/\");\n        }\n\n        /// <summary>\n        /// Add a new cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        /// <param name=\"options\"></param>\n        public void Append(string key, string value, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n            bool expiresHasValue = options.Expires.HasValue;\n\n            string setCookieValue = string.Concat(\n                Uri.EscapeDataString(key),\n                \"=\",\n                Uri.EscapeDataString(value ?? string.Empty),\n                !domainHasValue ? null : \"; domain=\",\n                !domainHasValue ? null : options.Domain,\n                !pathHasValue ? null : \"; path=\",\n                !pathHasValue ? null : options.Path,\n                !expiresHasValue ? null : \"; expires=\",\n                !expiresHasValue ? null : options.Expires.Value.ToString(\"ddd, dd-MMM-yyyy HH:mm:ss \", CultureInfo.InvariantCulture) + \"GMT\",\n                !options.Secure ? null : \"; secure\",\n                !options.HttpOnly ? null : \"; HttpOnly\");\n            Headers.AppendValues(\"Set-Cookie\", setCookieValue);\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        public void Delete(string key)\n        {\n            Func<string, bool> predicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n\n            var deleteCookies = new[] { Uri.EscapeDataString(key) + \"=; expires=Thu, 01-Jan-1970 00:00:00 GMT\" };\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues == null || existingValues.Count == 0)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, deleteCookies);\n            }\n            else\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !predicate(value)).Concat(deleteCookies).ToArray());\n            }\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"options\"></param>\n        public void Delete(string key, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n\n            Func<string, bool> rejectPredicate;\n            if (domainHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"domain=\" + options.Domain, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else if (pathHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"path=\" + options.Path, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else\n            {\n                rejectPredicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n            }\n\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues != null)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !rejectPredicate(value)).ToArray());\n            }\n\n            Append(key, string.Empty, new CookieOptions\n            {\n                Path = options.Path,\n                Domain = options.Domain,\n                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),\n            });\n        }\n    }\n\n\n    static partial class IOwinResponseExtension \n    {\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"response\">The owin response</param>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public static void OnSendingHeaders<T>(this IOwinResponse response, Action<T> callback, T state)\n        {\n            if (response == null) {\n                throw new ArgumentNullException(\"response\");\n            }\n            Action<object> innerCallback = innerState => callback((T)innerState);\n            response.OnSendingHeaders(innerCallback, state);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "src/chapter08/OwinMiddlewareTests/SampleTest.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\nusing Xunit;\nusing LibOwin;\n\n\nnamespace OwinMiddlewareTests\n{\n    \n    using AppFunc = Func<IDictionary<string, object>, Task>;\n    \n    // see example explanation on xUnit.net website:\n    // https://xunit.github.io/docs/getting-started-dnx.html\n    public class SampleTest\n    {\n        private AppFunc noOp = env => Task.FromResult(0);\n        \n        private Func<AppFunc, AppFunc> MW =\n         next => async env => \n        {\n          var ctx = new OwinContext(env);\n          if (ctx.Request.Path.Value == \"/test/path\")\n            ctx.Response.StatusCode = 404;\n          else\n            await next(env);\n        };\n        \n        private Func<AppFunc, AppFunc> ConsoleMV =\n          next => env =>\n          {\n            var context = new OwinContext(env);\n            var method = context.Request.Method;\n            var path = context.Request.Path;\n            System.Console.WriteLine($\"Got request: {method} {path}\");\n            return next(env);\n          };\n\n        [Fact]\n        public void CreateInvokeLambdaMw()\n        {\n          var ctx = new OwinContext();\n          ctx.Request.Scheme = LibOwin.Infrastructure.Constants.Https;\n          ctx.Request.Path = new PathString(\"/test/path\");\n          ctx.Request.Method = \"GET\";\n          \n          var pipeline = ConsoleMV(MW(noOp));\n          \n          var env = ctx.Environment;\n          pipeline(env);\n          \n          Assert.Equal(404, ctx.Response.StatusCode);\n        }\n\n        int Add(int x, int y)\n        {\n            return x + y;\n        }\n    }\n    \n    public class ConsoleMiddleware\n    {\n      private AppFunc next;\n      \n      public ConsoleMiddleware(AppFunc next)\n      {\n        this.next = next;\n      }\n\n      public Task Invoke(IDictionary<string, object> env)\n      {        \n        var context = new OwinContext(env);\n        var method = context.Request.Method;\n        var path = context.Request.Path;\n        System.Console.WriteLine($\"Got request: {method} {path}\");\n        return next(env);\n      }\n    }\n}\n"
  },
  {
    "path": "src/chapter08/OwinMiddlewareTests/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n\n  \"buildOptions\": {\n    \"preserveCompilationContext\": true\n  },\n\n  \"dependencies\": {\n    \"dotnet-test-xunit\": \"2.2.0-preview2-build1029\",\n    \"Microsoft.NETCore.App\": {                      \n      \"version\": \"1.0.0\",                           \n      \"type\": \"platform\"                            \n    },                                              \n    \"xunit\": \"2.1.0\",\n    \"System.Security.Claims\": \"4.0.1\",\n    \"System.Globalization\": \"4.0.11\"  \n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ],\n      \"dependencies\": {\n      }\n    }\n  },\n\n  \"testRunner\": \"xunit\",\n\n  \"tooling\": {\n    \"defaultNamespace\": \"OwinMiddlewareTests\"\n  }\n}\n"
  },
  {
    "path": "src/chapter10/.idea.ch10/riderModule.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"RIDER_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\">\n    <content url=\"file://$MODULE_DIR$/..\">\n      <sourceFolder url=\"file://$MODULE_DIR$/..\" isTestSource=\"false\" />\n    </content>\n    <content url=\"file://C:/projects/Nancy/src/Nancy\">\n      <sourceFolder url=\"file://C:/projects/Nancy/src/Nancy\" isTestSource=\"false\" />\n    </content>\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n  </component>\n</module>"
  },
  {
    "path": "src/chapter10/ApiGatewayMock/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/chapter10/ApiGatewayMock/ApiGatewayMock.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>fe109a02-bf1b-46fc-87c8-2a68781ce8a4</ProjectGuid>\n    <RootNamespace>ApiGatewayMock</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/chapter10/ApiGatewayMock/LoyalProgramClient.cs",
    "content": "using System;\nusing System.Net.Http;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Newtonsoft.Json;\nusing Polly;\n\nnamespace ApiGatewayMock\n{\n  public class LoyaltyProgramClient\n  {\n    private static Policy exponentialRetryPolicy =\n      Policy\n        .Handle<Exception>()\n        .WaitAndRetryAsync(\n                           3,\n                           attempt => TimeSpan.FromMilliseconds(100*Math.Pow(2, attempt)),\n                           (_, __) => Console.WriteLine(\"retrying...\" + _)\n        );\n\n    private static Policy circuitBreaker =\n      Policy\n        .Handle<Exception>()\n        .CircuitBreaker(5, TimeSpan.FromMinutes(5));\n\n    private string hostName;\n    private readonly IHttpClientFactory httpClientFactory;\n\n    public LoyaltyProgramClient(\n      string loyalProgramMicroserviceHostName, \n      IHttpClientFactory httpClientFactory)\n    {\n      this.hostName = loyalProgramMicroserviceHostName;\n      this.httpClientFactory = httpClientFactory;\n    }\n\n    public async Task<HttpResponseMessage> QueryUser(int userId)\n    {\n      return await circuitBreaker.ExecuteAsync(() => DoUserQuery(userId)).ConfigureAwait(false);\n    }\n\n    private async Task<HttpResponseMessage> DoUserQuery(int userId)\n    {\n      var userResource = $\"/users/{userId}\";\n      using (var httpClient = await this.httpClientFactory.Create(new Uri($\"http://{this.hostName}\"), \"loyalty_program_write\").ConfigureAwait(false))\n      {\n        var response = await httpClient.GetAsync(userResource).ConfigureAwait(false);\n        ThrowOnTransientFailure(response);\n        return response;\n      }\n    }\n\n    private static void ThrowOnTransientFailure(HttpResponseMessage response)\n    {\n      if (((int) response.StatusCode) < 200 || ((int) response.StatusCode) > 499)\n        throw new Exception(response.StatusCode.ToString());\n    }\n\n    public async Task<HttpResponseMessage> RegisterUser(LoyaltyProgramUser newUser)\n    {\n      return await exponentialRetryPolicy.ExecuteAsync(() => DoRegisterUser(newUser)).ConfigureAwait(false);\n    }\n\n    private async Task<HttpResponseMessage> DoRegisterUser(LoyaltyProgramUser newUser)\n    {\n      using (var httpClient = await this.httpClientFactory.Create(new Uri($\"http://{this.hostName}\"), \"loyalty_program_write\").ConfigureAwait(false))\n      {\n        var response =\n          await\n          httpClient.PostAsync(\"/users/\",\n                               new StringContent(JsonConvert.SerializeObject(newUser), Encoding.UTF8, \"application/json\")).ConfigureAwait(false);\n        ThrowOnTransientFailure(response);\n        return response;\n      }\n    }\n\n    public async Task<HttpResponseMessage> UpdateUser(LoyaltyProgramUser user)\n    {\n      return await exponentialRetryPolicy.ExecuteAsync(() => DoUpdateUser(user)).ConfigureAwait(false);\n    }\n\n    private async Task<HttpResponseMessage> DoUpdateUser(LoyaltyProgramUser user)\n    {\n      using (var httpClient = await this.httpClientFactory.Create(new Uri($\"http://{this.hostName}\"), \"loyalty_program_write\").ConfigureAwait(false))\n      {\n        httpClient.BaseAddress = new Uri($\"http://{this.hostName}\");\n        var response =\n          await\n          httpClient.PutAsync($\"/users/{user.Id}\",\n                              new StringContent(JsonConvert.SerializeObject(user), Encoding.UTF8, \"application/json\")).ConfigureAwait(false);\n        ThrowOnTransientFailure(response);\n        return response;\n      }\n    }\n  }\n\n  public class LoyaltyProgramUser\n  {\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public int LoyaltyPoints { get; set; }\n    public LoyaltyProgramSettings Settings { get; set; }\n  }\n\n  public class LoyaltyProgramSettings\n  {\n    public string[] Interests { get; set; }\n  }\n}\n"
  },
  {
    "path": "src/chapter10/ApiGatewayMock/Program.cs",
    "content": "using static System.Console;\n\nnamespace ApiGatewayMock\n{\n  using System;\n  using System.Linq;\n  using System.Net;\n  using System.Net.Http;\n  using System.Net.Http.Headers;\n  using System.Threading.Tasks;\n  using IdentityModel.Client;\n  using Newtonsoft.Json;\n\n  public interface IHttpClientFactory\n  {\n    Task<HttpClient> Create(Uri uri, string scope);\n  }\n\n  public class HttpClientFactory : IHttpClientFactory\n  {\n    private readonly TokenClient tokenClient;\n\n    public HttpClientFactory()\n    {\n      this.tokenClient = new TokenClient(\n        \"http://localhost:5001/connect/token\",\n        \"api_gateway\",\n        \"secret\");\n    }\n\n    public async Task<HttpClient> Create(Uri uri, string scope)\n    {\n      var response = await this.tokenClient.RequestClientCredentialsAsync(scope).ConfigureAwait(false);\n      var client = new HttpClient() {BaseAddress = uri};\n      client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(\"Bearer\", response.AccessToken);\n      return client;\n    }\n  }\n\n\n  public class Program\n  {\n    private LoyaltyProgramClient client;\n\n    public static void Main(string[] arg) => new Program().Main();\n\n    public void Main()\n    {\n      this.client = new LoyaltyProgramClient(\"localhost:5000\", new HttpClientFactory());\n      WriteLine(\"Welcome to the API Gateway Mock.\");\n\n      var cont = true;\n      while (cont)\n      {\n        WriteLine();\n        WriteLine();\n        WriteLine(\"********************\");\n        WriteLine(\"Choose one of:\");\n        WriteLine(\"q <userid> - to query the Loyalty Program Microservice for a user with id <userid>.\");\n        WriteLine(\"r <userid> - to register a user with id <userid> with the Loyalty Program Microservice.\");\n        WriteLine(\"u <userid> <interests> - to update a user with new comman separated interests\");\n        WriteLine(\"exit - to exit\");\n        WriteLine(\"********************\");\n        var cmd = ReadLine();\n        cont = ProcessCommand(cmd);\n      }\n    }\n\n    private bool ProcessCommand(string cmd)\n    {\n      if (\"exit\".Equals(cmd))\n        return false;\n      if (cmd.StartsWith(\"q\"))\n        ProcessUserQuery(cmd);\n      else if (cmd.StartsWith(\"r\"))\n        ProcessUserRegistration(cmd);\n      else if (cmd.StartsWith(\"u\"))\n        ProcessUpdateUser(cmd);\n      else\n        WriteLine(\"Did not understand command :(\");\n      return true;\n    }\n\n    private void ProcessUserQuery(string cmd)\n    {\n      int userId;\n      if (!int.TryParse(cmd.Substring(1), out userId))\n        WriteLine(\"Please specify user id as an int\");\n      else\n      {\n        var response = this.client.QueryUser(userId).Result;\n        PrettyPrintResponse(response);\n      }\n    }\n\n    private void ProcessUserRegistration(string cmd)\n    {\n      var newUser = new LoyaltyProgramUser {Name = cmd.Substring(1).Trim()};\n      var response = this.client.RegisterUser(newUser).Result;\n      PrettyPrintResponse(response);\n    }\n\n    private static async void PrettyPrintResponse(HttpResponseMessage response)\n    {\n      WriteLine(\"Status code: \" + (response?.StatusCode.ToString() ?? \"command failed\"));\n      WriteLine(\"Headers: \" + (response?.Headers.Aggregate(\"\", (acc, h) => acc + \"\\n\\t\" + h.Key + \": \" + h.Value) ?? \"\"));\n      WriteLine(\"Body: \" + await (response?.Content.ReadAsStringAsync() ?? Task.FromResult(\"\")).ConfigureAwait(false));\n    }\n\n    private async void ProcessUpdateUser(string cmd)\n    {\n      int userId;\n      if (!int.TryParse(cmd.Split(' ').Skip(1).First(), out userId))\n        WriteLine(\"Plaese speciffy user id as an int\");\n      else\n      {\n        var response = this.client.QueryUser(userId).Result;\n        if (response.StatusCode == HttpStatusCode.OK)\n        {\n          var user = JsonConvert.DeserializeObject<LoyaltyProgramUser>(await response.Content.ReadAsStringAsync().ConfigureAwait(false));\n          var newInterests = cmd.Substring(cmd.IndexOf(' ', 2)).Split(',').Select(i => i.Trim());\n          user.Settings =\n            new LoyaltyProgramSettings\n            {\n              Interests =\n                user.Settings?.Interests.Union(newInterests).ToArray()\n                ?? newInterests.ToArray()\n            };\n          PrettyPrintResponse(this.client.UpdateUser(user).Result);\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/chapter10/ApiGatewayMock/project.json",
    "content": "{\n  \"version\": \"1.0.0-*\",\n  \"buildOptions\": {\n    \"emitEntryPoint\": true\n  },\n\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"type\": \"platform\",\n      \"version\": \"1.0.0\"\n    },\n    \"Newtonsoft.Json\": \"8.0.4-beta1\",\n    \"Polly\": \"4.2.1\",\n    \"IdentityModel\": \"2.0.0-beta3\",\n    \"System.Net.Http\": \"4.1.0\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": \"dnxcore50\"\n    }\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"ApiGatewayMock\"\n  }\n}\n"
  },
  {
    "path": "src/chapter10/Login/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/chapter10/Login/Configuration/Clients.cs",
    "content": "﻿namespace Login.Configuration\n{\n  using System.Collections.Generic;\n  using IdentityServer4.Models;\n\n  public class Clients\n  {\n    public static IEnumerable<Client> Get() =>\n      new List<Client>\n      {\n        new Client\n        {\n          ClientName = \"API Gateway\",\n          ClientId = \"api_gateway\",\n          ClientSecrets = new List<Secret>\n          {\n            new Secret(\"secret\".Sha256())\n          },\n          AllowedScopes = new List<string>\n          {\n            \"loyalty_program_write\",\n          },\n          AllowedGrantTypes = GrantTypes.ClientCredentials\n        },\n\n        new Client\n        {\n          ClientName = \"Web Client\",\n          ClientId = \"web\",\n\n          RedirectUris = new List<string>\n          {\n            \"http://localhost:5003/signin-oidc\",\n          },\n          PostLogoutRedirectUris = new List<string>\n          {\n            \"http://localhost:5003/\",\n          },\n\n          AllowedScopes = new List<string>\n          {\n                        \"openid\",\n                        \"email\",\n                        \"profile\",\n          }\n        }\n      };\n  }\n}"
  },
  {
    "path": "src/chapter10/Login/Configuration/Scopes.cs",
    "content": "﻿namespace Login.Configuration\n{\n  using System.Collections.Generic;\n  using IdentityServer4.Models;\n\n  public class Scopes\n  {\n    public static IEnumerable<Scope> Get() =>\n      new[]\n      {\n        // standard OpenID Connect scopes\n        StandardScopes.OpenId,\n        StandardScopes.ProfileAlwaysInclude,\n        StandardScopes.EmailAlwaysInclude,\n        new Scope\n        {\n          Name = \"loyalty_program_write\",\n          DisplayName = \"Loyalty Program write access\",\n          Type = ScopeType.Resource,\n        }\n      };\n  }\n}"
  },
  {
    "path": "src/chapter10/Login/Configuration/Users.cs",
    "content": "﻿namespace Login.Configuration\n{\n  using System.Collections.Generic;\n  using System.Security.Claims;\n  using IdentityModel;\n  using IdentityServer4.Services.InMemory;\n\n  static class Users\n  {\n    public static List<InMemoryUser> Get()\n      =>\n        new List<InMemoryUser>\n        {\n          new InMemoryUser{Subject = \"818727\", Username = \"alice\", Password = \"alice\",\n            Claims = new[]\n            {\n              new Claim(JwtClaimTypes.Name, \"Alice Smith\"),\n              new Claim(JwtClaimTypes.GivenName, \"Alice\"),\n              new Claim(JwtClaimTypes.FamilyName, \"Smith\"),\n              new Claim(JwtClaimTypes.Email, \"AliceSmith@email.com\"),\n              new Claim(JwtClaimTypes.EmailVerified, \"true\", ClaimValueTypes.Boolean),\n              new Claim(JwtClaimTypes.Role, \"User\"),\n              new Claim(JwtClaimTypes.Id, \"1\", ClaimValueTypes.Integer64)\n            }\n          },\n          new InMemoryUser{Subject = \"88421113\", Username = \"bob\", Password = \"bob\",\n            Claims = new[]\n            {\n              new Claim(JwtClaimTypes.Name, \"Bob Smith\"),\n              new Claim(JwtClaimTypes.GivenName, \"Bob\"),\n              new Claim(JwtClaimTypes.FamilyName, \"Smith\"),\n              new Claim(JwtClaimTypes.Email, \"BobSmith@email.com\"),\n              new Claim(JwtClaimTypes.EmailVerified, \"true\", ClaimValueTypes.Boolean),\n              new Claim(JwtClaimTypes.Role, \"User\"),\n              new Claim(JwtClaimTypes.Id, \"2\", ClaimValueTypes.Integer64)\n            }\n          }\n        };\n  }\n}"
  },
  {
    "path": "src/chapter10/Login/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/chapter10/Login/Login.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0.25123\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0.25123</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>f416d0b1-71ee-400e-91e2-fc2b047da208</ProjectGuid>\n    <RootNamespace>Login</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/chapter10/Login/Program.cs",
    "content": "namespace Login\n{\n  using System.IO;\n  using Microsoft.AspNetCore.Hosting;\n\n  public class Program\n  {\n    public static void Main(string[] args)\n    {\n      var host = new WebHostBuilder()\n        .UseKestrel()\n        .UseContentRoot(Directory.GetCurrentDirectory())\n        .UseIISIntegration()\n        .UseStartup<Startup>()\n        .UseUrls(\"http://localhost:5001\")\n        .Build();\n\n      host.Run();\n    }\n  }\n}\n"
  },
  {
    "path": "src/chapter10/Login/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"IdentityServer\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/chapter10/Login/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/chapter10/Login/Startup.cs",
    "content": "﻿namespace Login\n{\n  using System.IO;\n  using Microsoft.AspNetCore.Builder;\n  using Microsoft.AspNetCore.Hosting;\n  using System.Security.Cryptography.X509Certificates;\n  using Microsoft.AspNetCore.Http;\n  using Microsoft.Extensions.Logging;\n  using Microsoft.Extensions.DependencyInjection;\n\n  using Configuration;\n\n  public class Startup\n  {\n    private readonly IHostingEnvironment environment;\n\n    public Startup(IHostingEnvironment env)\n    {\n      this.environment = env;\n    }\n\n    public void ConfigureServices(IServiceCollection services)\n    {\n      var cert = new X509Certificate2(Path.Combine(this.environment.ContentRootPath, \"idsrv3test.pfx\"), \"idsrv3test\");\n\n      services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();\n      var builder = services.AddIdentityServer().SetSigningCredential(cert);\n\n      builder.AddInMemoryClients(Clients.Get());\n      builder.AddInMemoryScopes(Scopes.Get());\n      builder.AddInMemoryUsers(Users.Get());\n\n      services.AddMvc();\n    }\n\n    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)\n    {\n      loggerFactory.AddConsole(LogLevel.Trace);\n      loggerFactory.AddDebug(LogLevel.Trace);\n\n      app.UseCookieAuthentication(new CookieAuthenticationOptions\n      {\n        AuthenticationScheme = \"Temp\",\n        AutomaticAuthenticate = false,\n        AutomaticChallenge = false\n      });\n\n      app.UseIdentityServer();\n\n      app.UseStaticFiles();\n      app.UseMvcWithDefaultRoute();\n    }\n  }\n}\n"
  },
  {
    "path": "src/chapter10/Login/project.json",
    "content": "  {\n    \"dependencies\": {\n      \"Microsoft.NETCore.App\": {\n        \"version\": \"1.0.0\",\n        \"type\": \"platform\"\n      },\n      \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n      \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n      \"Microsoft.AspNetCore.StaticFiles\": \"1.0.0\",\n      \"Microsoft.AspNetCore.Mvc\": \"1.0.0\",\n      \"Microsoft.Extensions.Logging.Console\": \"1.0.0\",\n      \"Microsoft.Extensions.Logging.Debug\": \"1.0.0\",\n      \"IdentityServer4\": \"1.0.0-beta5\",\n      \"SeriLog\": \"2.0.0-rc-600\"\n    },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"IdentityServer\"\n  }\n}\n"
  },
  {
    "path": "src/chapter10/Login/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/.gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Microsoft Azure ApplicationInsights config file\nApplicationInsights.config\n\n# Windows Store app package directory\nAppPackages/\nBundleArtifacts/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\n\n# FAKE - F# Make\n.fake/\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/Application_Packages/LibOwin.cs",
    "content": "﻿// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.\n// Copyright (c) Damian Hickey. All rights reserved. See License.txt in the project root for license information.\n\n// https://github.com/damianh/LibOwin\n// Modifying this file may result in difficulties when upgrading the package.\n// All types are internal. Add a LIBOWIN_PUBLIC compilation symbol to make them public.\n\nnamespace LibOwin.Infrastructure\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Linq;\n\n    internal static partial class Constants\n    {\n        internal const string Https = \"HTTPS\";\n\n        internal const string HttpDateFormat = \"r\";\n\n        internal static partial class Headers\n        {\n            internal const string ContentType = \"Content-Type\";\n            internal const string CacheControl = \"Cache-Control\";\n            internal const string MediaType = \"Media-Type\";\n            internal const string Accept = \"Accept\";\n            internal const string Host = \"Host\";\n            internal const string ETag = \"ETag\";\n            internal const string Location = \"Location\";\n            internal const string ContentLength = \"Content-Length\";\n            internal const string SetCookie = \"Set-Cookie\";\n            internal const string Expires = \"Expires\";\n        }\n    }\n\n    internal struct HeaderSegment : IEquatable<HeaderSegment>\n    {\n        private readonly StringSegment _formatting;\n        private readonly StringSegment _data;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public HeaderSegment(StringSegment formatting, StringSegment data)\n        {\n            _formatting = formatting;\n            _data = data;\n        }\n\n        public StringSegment Formatting\n        {\n            get { return _formatting; }\n        }\n\n        public StringSegment Data\n        {\n            get { return _data; }\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegment other)\n        {\n            return _formatting.Equals(other._formatting) && _data.Equals(other._data);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegment && Equals((HeaderSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                return (_formatting.GetHashCode() * 397) ^ _data.GetHashCode();\n            }\n        }\n\n        public static bool operator ==(HeaderSegment left, HeaderSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegment left, HeaderSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n    }\n\n    internal struct HeaderSegmentCollection : IEnumerable<HeaderSegment>, IEquatable<HeaderSegmentCollection>\n    {\n        private readonly string[] _headers;\n\n        public HeaderSegmentCollection(string[] headers)\n        {\n            _headers = headers;\n        }\n\n        #region Equality members\n\n        public bool Equals(HeaderSegmentCollection other)\n        {\n            return Equals(_headers, other._headers);\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is HeaderSegmentCollection && Equals((HeaderSegmentCollection)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            return (_headers != null ? _headers.GetHashCode() : 0);\n        }\n\n        public static bool operator ==(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(HeaderSegmentCollection left, HeaderSegmentCollection right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public Enumerator GetEnumerator()\n        {\n            return new Enumerator(_headers);\n        }\n\n        IEnumerator<HeaderSegment> IEnumerable<HeaderSegment>.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        internal struct Enumerator : IEnumerator<HeaderSegment>\n        {\n            private readonly string[] _headers;\n            private int _index;\n\n            private string _header;\n            private int _headerLength;\n            private int _offset;\n\n            private int _leadingStart;\n            private int _leadingEnd;\n            private int _valueStart;\n            private int _valueEnd;\n            private int _trailingStart;\n\n            private Mode _mode;\n\n            private static readonly string[] NoHeaders = new string[0];\n\n            public Enumerator(string[] headers)\n            {\n                _headers = headers ?? NoHeaders;\n                _header = string.Empty;\n                _headerLength = -1;\n                _index = -1;\n                _offset = -1;\n                _leadingStart = -1;\n                _leadingEnd = -1;\n                _valueStart = -1;\n                _valueEnd = -1;\n                _trailingStart = -1;\n                _mode = Mode.Leading;\n            }\n\n            private enum Mode\n            {\n                Leading,\n                Value,\n                ValueQuoted,\n                Trailing,\n                Produce,\n            }\n\n            private enum Attr\n            {\n                Value,\n                Quote,\n                Delimiter,\n                Whitespace\n            }\n\n            public HeaderSegment Current\n            {\n                get\n                {\n                    return new HeaderSegment(\n                        new StringSegment(_header, _leadingStart, _leadingEnd - _leadingStart),\n                        new StringSegment(_header, _valueStart, _valueEnd - _valueStart));\n                }\n            }\n\n            object IEnumerator.Current\n            {\n                get { return Current; }\n            }\n\n            public void Dispose()\n            {\n            }\n\n            public bool MoveNext()\n            {\n                while (true)\n                {\n                    if (_mode == Mode.Produce)\n                    {\n                        _leadingStart = _trailingStart;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        if (_offset == _headerLength &&\n                            _leadingStart != -1 &&\n                            _leadingStart != _offset)\n                        {\n                            // Also produce trailing whitespace\n                            _leadingEnd = _offset;\n                            return true;\n                        }\n                        _mode = Mode.Leading;\n                    }\n\n                    // if end of a string\n                    if (_offset == _headerLength)\n                    {\n                        ++_index;\n                        _offset = -1;\n                        _leadingStart = 0;\n                        _leadingEnd = -1;\n                        _valueStart = -1;\n                        _valueEnd = -1;\n                        _trailingStart = -1;\n\n                        // if that was the last string\n                        if (_index == _headers.Length)\n                        {\n                            // no more move nexts\n                            return false;\n                        }\n\n                        // grab the next string\n                        _header = _headers[_index] ?? string.Empty;\n                        _headerLength = _header.Length;\n                    }\n                    while (true)\n                    {\n                        ++_offset;\n                        char ch = _offset == _headerLength ? (char)0 : _header[_offset];\n                        // todo - array of attrs\n                        Attr attr = char.IsWhiteSpace(ch) ? Attr.Whitespace : ch == '\\\"' ? Attr.Quote : (ch == ',' || ch == (char)0) ? Attr.Delimiter : Attr.Value;\n\n                        switch (_mode)\n                        {\n                            case Mode.Leading:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _leadingEnd = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        _leadingEnd = _offset;\n                                        _valueStart = _offset;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Value:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Delimiter:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Value:\n                                        // more\n                                        break;\n                                    case Attr.Whitespace:\n                                        _valueEnd = _offset;\n                                        _trailingStart = _offset;\n                                        _mode = Mode.Trailing;\n                                        break;\n                                }\n                                break;\n                            case Mode.ValueQuoted:\n                                switch (attr)\n                                {\n                                    case Attr.Quote:\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Delimiter:\n                                        if (ch == (char)0)\n                                        {\n                                            _valueEnd = _offset;\n                                            _trailingStart = _offset;\n                                            _mode = Mode.Produce;\n                                        }\n                                        break;\n                                    case Attr.Value:\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                            case Mode.Trailing:\n                                switch (attr)\n                                {\n                                    case Attr.Delimiter:\n                                        _mode = Mode.Produce;\n                                        break;\n                                    case Attr.Quote:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.ValueQuoted;\n                                        break;\n                                    case Attr.Value:\n                                        // back into value\n                                        _trailingStart = -1;\n                                        _valueEnd = -1;\n                                        _mode = Mode.Value;\n                                        break;\n                                    case Attr.Whitespace:\n                                        // more\n                                        break;\n                                }\n                                break;\n                        }\n                        if (_mode == Mode.Produce)\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n\n            public void Reset()\n            {\n                _index = 0;\n                _offset = 0;\n                _leadingStart = 0;\n                _leadingEnd = 0;\n                _valueStart = 0;\n                _valueEnd = 0;\n            }\n        }\n    }\n\n    internal struct StringSegment : IEquatable<StringSegment>\n    {\n        private readonly string _buffer;\n        private readonly int _offset;\n        private readonly int _count;\n\n        // <summary>\n        // Initializes a new instance of the <see cref=\"T:System.Object\"/> class.\n        // </summary>\n        public StringSegment(string buffer, int offset, int count)\n        {\n            _buffer = buffer;\n            _offset = offset;\n            _count = count;\n        }\n\n        public string Buffer\n        {\n            get { return _buffer; }\n        }\n\n        public int Offset\n        {\n            get { return _offset; }\n        }\n\n        public int Count\n        {\n            get { return _count; }\n        }\n\n        public string Value\n        {\n            get { return _offset == -1 ? null : _buffer.Substring(_offset, _count); }\n        }\n\n        public bool HasValue\n        {\n            get { return _offset != -1 && _count != 0 && _buffer != null; }\n        }\n\n        #region Equality members\n\n        public bool Equals(StringSegment other)\n        {\n            return string.Equals(_buffer, other._buffer) && _offset == other._offset && _count == other._count;\n        }\n\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n\n            return obj is StringSegment && Equals((StringSegment)obj);\n        }\n\n        public override int GetHashCode()\n        {\n            unchecked\n            {\n                int hashCode = (_buffer != null ? _buffer.GetHashCode() : 0);\n                hashCode = (hashCode * 397) ^ _offset;\n                hashCode = (hashCode * 397) ^ _count;\n                return hashCode;\n            }\n        }\n\n        public static bool operator ==(StringSegment left, StringSegment right)\n        {\n            return left.Equals(right);\n        }\n\n        public static bool operator !=(StringSegment left, StringSegment right)\n        {\n            return !left.Equals(right);\n        }\n\n        #endregion\n\n        public bool StartsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool EndsWith(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count < textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset + _count - textLength, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public bool Equals(string text, StringComparison comparisonType)\n        {\n            if (text == null)\n            {\n                throw new ArgumentNullException(\"text\");\n            }\n            int textLength = text.Length;\n            if (!HasValue || _count != textLength)\n            {\n                return false;\n            }\n\n            return string.Compare(_buffer, _offset, text, 0, textLength, comparisonType) == 0;\n        }\n\n        public string Substring(int offset, int length)\n        {\n            return _buffer.Substring(_offset + offset, length);\n        }\n\n        public StringSegment Subsegment(int offset, int length)\n        {\n            return new StringSegment(_buffer, _offset + offset, length);\n        }\n\n        public override string ToString()\n        {\n            return Value ?? string.Empty;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AddCookieCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, string>)state;\n            if (!dictionary.ContainsKey(name))\n            {\n                dictionary.Add(name, value);\n            }\n        };\n\n        private static readonly char[] SemicolonAndComma = new[] { ';', ',' };\n\n        internal static IDictionary<string, string> GetCookies(IOwinRequest request)\n        {\n            var cookies = request.Get<IDictionary<string, string>>(\"Microsoft.Owin.Cookies#dictionary\");\n            if (cookies == null)\n            {\n                cookies = new Dictionary<string, string>(StringComparer.Ordinal);\n                request.Set(\"Microsoft.Owin.Cookies#dictionary\", cookies);\n            }\n\n            string text = GetHeader(request.Headers, \"Cookie\");\n            if (request.Get<string>(\"Microsoft.Owin.Cookies#text\") != text)\n            {\n                cookies.Clear();\n                ParseDelimited(text, SemicolonAndComma, AddCookieCallback, cookies);\n                request.Set(\"Microsoft.Owin.Cookies#text\", text);\n            }\n            return cookies;\n        }\n\n        internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)\n        {\n            int textLength = text.Length;\n            int equalIndex = text.IndexOf('=');\n            if (equalIndex == -1)\n            {\n                equalIndex = textLength;\n            }\n            int scanIndex = 0;\n            while (scanIndex < textLength)\n            {\n                int delimiterIndex = text.IndexOfAny(delimiters, scanIndex);\n                if (delimiterIndex == -1)\n                {\n                    delimiterIndex = textLength;\n                }\n                if (equalIndex < delimiterIndex)\n                {\n                    while (scanIndex != equalIndex && char.IsWhiteSpace(text[scanIndex]))\n                    {\n                        ++scanIndex;\n                    }\n                    string name = text.Substring(scanIndex, equalIndex - scanIndex);\n                    string value = text.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);\n                    callback(\n                        Uri.UnescapeDataString(name.Replace('+', ' ')),\n                        Uri.UnescapeDataString(value.Replace('+', ' ')),\n                        state);\n                    equalIndex = text.IndexOf('=', delimiterIndex);\n                    if (equalIndex == -1)\n                    {\n                        equalIndex = textLength;\n                    }\n                }\n                scanIndex = delimiterIndex + 1;\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        public static string GetHeader(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        public static IEnumerable<string> GetHeaderSplit(IDictionary<string, string[]> headers, string key)\n        {\n            string[] values = GetHeaderUnmodified(headers, key);\n            return values == null ? null : GetHeaderSplitImplementation(values);\n        }\n\n        private static IEnumerable<string> GetHeaderSplitImplementation(string[] values)\n        {\n            foreach (var segment in new HeaderSegmentCollection(values))\n            {\n                if (segment.Data.HasValue)\n                {\n                    yield return DeQuote(segment.Data.Value);\n                }\n            }\n        }\n\n        public static string[] GetHeaderUnmodified(IDictionary<string, string[]> headers, string key)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            string[] values;\n            return headers.TryGetValue(key, out values) ? values : null;\n        }\n\n        public static void SetHeader(IDictionary<string, string[]> headers, string key, string value)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { value };\n            }\n        }\n\n        public static void SetHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = new[] { string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        // Quote items that contain comas and are not already quoted.\n        private static string QuoteIfNeeded(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Contains(','))\n            {\n                if (value[0] != '\"' || value[value.Length - 1] != '\"')\n                {\n                    value = '\"' + value + '\"';\n                }\n            }\n\n            return value;\n        }\n\n        private static string DeQuote(string value)\n        {\n            if (string.IsNullOrWhiteSpace(value))\n            {\n                // Ignore\n            }\n            else if (value.Length > 1 && value[0] == '\"' && value[value.Length - 1] == '\"')\n            {\n                value = value.Substring(1, value.Length - 2);\n            }\n\n            return value;\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            if (string.IsNullOrWhiteSpace(key))\n            {\n                throw new ArgumentNullException(\"key\");\n            }\n            if (values == null || values.Length == 0)\n            {\n                headers.Remove(key);\n            }\n            else\n            {\n                headers[key] = values;\n            }\n        }\n\n        public static void SetHeaderUnmodified(IDictionary<string, string[]> headers, string key, IEnumerable<string> values)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n            headers[key] = values.ToArray();\n        }\n\n        public static void AppendHeader(IDictionary<string, string[]> headers, string key, string values)\n        {\n            if (string.IsNullOrWhiteSpace(values))\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeader(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + values };\n            }\n        }\n\n        public static void AppendHeaderJoined(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string existing = GetHeader(headers, key);\n            if (existing == null)\n            {\n                SetHeaderJoined(headers, key, values);\n            }\n            else\n            {\n                headers[key] = new[] { existing + \",\" + string.Join(\",\", values.Select(value => QuoteIfNeeded(value))) };\n            }\n        }\n\n        public static void AppendHeaderUnmodified(IDictionary<string, string[]> headers, string key, params string[] values)\n        {\n            if (values == null || values.Length == 0)\n            {\n                return;\n            }\n\n            string[] existing = GetHeaderUnmodified(headers, key);\n            if (existing == null)\n            {\n                SetHeaderUnmodified(headers, key, values);\n            }\n            else\n            {\n                SetHeaderUnmodified(headers, key, existing.Concat(values));\n            }\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        private static readonly Action<string, string, object> AppendItemCallback = (name, value, state) =>\n        {\n            var dictionary = (IDictionary<string, List<String>>)state;\n\n            List<string> existing;\n            if (!dictionary.TryGetValue(name, out existing))\n            {\n                dictionary.Add(name, new List<string>(1) { value });\n            }\n            else\n            {\n                existing.Add(value);\n            }\n        };\n\n        private static readonly char[] AmpersandAndSemicolon = new[] { '&', ';' };\n\n        internal static IDictionary<string, string[]> GetQuery(IOwinRequest request)\n        {\n            var query = request.Get<IDictionary<string, string[]>>(\"Microsoft.Owin.Query#dictionary\");\n            if (query == null)\n            {\n                query = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n                request.Set(\"Microsoft.Owin.Query#dictionary\", query);\n            }\n\n            string text = request.QueryString.Value;\n            if (request.Get<string>(\"Microsoft.Owin.Query#text\") != text)\n            {\n                query.Clear();\n                var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n                ParseDelimited(text, AmpersandAndSemicolon, AppendItemCallback, accumulator);\n                foreach (var kv in accumulator)\n                {\n                    query.Add(kv.Key, kv.Value.ToArray());\n                }\n                request.Set(\"Microsoft.Owin.Query#text\", text);\n            }\n            return query;\n        }\n\n        internal static IFormCollection GetForm(string text)\n        {\n            IDictionary<string, string[]> form = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            var accumulator = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);\n            ParseDelimited(text, new[] { '&' }, AppendItemCallback, accumulator);\n            foreach (var kv in accumulator)\n            {\n                form.Add(kv.Key, kv.Value.ToArray());\n            }\n            return new FormCollection(form);\n        }\n\n        internal static string GetJoinedValue(IDictionary<string, string[]> store, string key)\n        {\n            string[] values = GetUnmodifiedValues(store, key);\n            return values == null ? null : string.Join(\",\", values);\n        }\n\n        internal static string[] GetUnmodifiedValues(IDictionary<string, string[]> store, string key)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n            string[] values;\n            return store.TryGetValue(key, out values) ? values : null;\n        }\n    }\n\n    internal static partial class OwinHelpers\n    {\n        internal static string GetHost(IOwinRequest request)\n        {\n            IHeaderDictionary headers = request.Headers;\n\n            string host = GetHeader(headers, \"Host\");\n            if (!string.IsNullOrWhiteSpace(host))\n            {\n                return host;\n            }\n\n            string localIpAddress = request.LocalIpAddress ?? \"localhost\";\n            var localPort = request.Get<string>(OwinConstants.CommonKeys.LocalPort);\n            return string.IsNullOrWhiteSpace(localPort) ? localIpAddress : (localIpAddress + \":\" + localPort);\n        }\n    }\n}\n\nnamespace LibOwin\n{\n    using System;\n    using System.Collections;\n    using System.Collections.Generic;\n    using System.Globalization;\n    using System.IO;\n    using System.Linq;\n    using System.Security.Claims;\n    using System.Security.Principal;\n    using System.Text;\n    using System.Threading;\n    using System.Threading.Tasks;\n    using LibOwin.Infrastructure;\n\n    #if LIBOWIN_PUBLIC\n\n    public partial class CookieOptions { }\n    public partial class FormCollection { }\n    public partial class HeaderDictionary { }\n    public partial struct HostString { }\n    public partial interface IFormCollection { }\n    public partial interface IHeaderDictionary { }\n    public partial interface IOwinContext { }\n    public partial interface IOwinRequest { }\n    public partial interface IOwinResponse { }\n    public partial interface IReadableStringCollection { }\n    public partial class OwinContext { }\n    public partial class OwinRequest { }\n    public partial class OwinResponse { }\n    public partial struct PathString { }\n    public partial struct QueryString { }\n    public partial class ReadableStringCollection { }\n    public partial class RequestCookieCollection { }\n    public partial class ResponseCookieCollection { }\n    public partial class IOwinResponseExtension { }\n\n    #endif\n\n    /// <summary>\n    /// Options used to create a new cookie.\n    /// </summary>\n    partial class CookieOptions\n    {\n        /// <summary>\n        /// Creates a default cookie with a path of '/'.\n        /// </summary>\n        public CookieOptions()\n        {\n            Path = \"/\";\n        }\n\n        /// <summary>\n        /// Gets or sets the domain to associate the cookie with.\n        /// </summary>\n        /// <returns>The domain to associate the cookie with.</returns>\n        public string Domain { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cookie path.\n        /// </summary>\n        /// <returns>The cookie path.</returns>\n        public string Path { get; set; }\n\n        /// <summary>\n        /// Gets or sets the expiration date and time for the cookie.\n        /// </summary>\n        /// <returns>The expiration date and time for the cookie.</returns>\n        public DateTime? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether to transmit the cookie using Secure Sockets Layer (SSL)—that is, over HTTPS only.\n        /// </summary>\n        /// <returns>true to transmit the cookie only over an SSL connection (HTTPS); otherwise, false.</returns>\n        public bool Secure { get; set; }\n\n        /// <summary>\n        /// Gets or sets a value that indicates whether a cookie is accessible by client-side script.\n        /// </summary>\n        /// <returns>true if a cookie is accessible by client-side script; otherwise, false.</returns>\n        public bool HttpOnly { get; set; }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial class FormCollection : ReadableStringCollection, IFormCollection\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.FormCollection\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The store for the form.</param>\n        public FormCollection(IDictionary<string, string[]> store)\n            : base(store)\n        {}\n    }\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial class HeaderDictionary : IHeaderDictionary\n    {\n        /// <summary>\n        /// Initializes a new instance of the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> class.\n        /// </summary>\n        /// <param name=\"store\">The underlying data store.</param>\n        public HeaderDictionary(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Gets an <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.ICollection\" /> that contains the keys in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public ICollection<string> Keys\n        {\n            get { return Store.Keys; }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        public ICollection<string[]> Values\n        {\n            get { return Store.Values; }\n        }\n\n        /// <summary>\n        /// Gets the number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />;.\n        /// </summary>\n        /// <returns>The number of elements contained in the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</returns>\n        public int Count\n        {\n            get { return Store.Count; }\n        }\n\n        /// <summary>\n        /// Gets a value that indicates whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode.\n        /// </summary>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> is in read-only mode; otherwise, false.</returns>\n        public bool IsReadOnly\n        {\n            get { return Store.IsReadOnly; }\n        }\n\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n            set { Set(key, value); }\n        }\n\n        /// <summary>\n        /// Throws KeyNotFoundException if the key is not present.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns></returns>\n        string[] IDictionary<string, string[]>.this[string key]\n        {\n            get { return Store[key]; }\n            set { Store[key] = value; }\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        /// Returns an enumerator that iterates through a collection.\n        /// </summary>\n        /// <returns>An <see cref=\"T:System.Collections.IEnumerator\" /> object that can be used to iterate through the collection.</returns>\n        IEnumerator IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetHeader(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection without modification, or null if the key is not present.</returns>\n        public IList<string> GetValues(string key)\n        {\n            return OwinHelpers.GetHeaderUnmodified(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        public IList<string> GetCommaSeparatedValues(string key)\n        {\n            IEnumerable<string> values = OwinHelpers.GetHeaderSplit(Store, key);\n            return values == null ? null : values.ToList();\n        }\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Append(string key, string value)\n        {\n            OwinHelpers.AppendHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void AppendCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.AppendHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        public void Set(string key, string value)\n        {\n            OwinHelpers.SetHeader(Store, key, value);\n        }\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderUnmodified(Store, key, values);\n        }\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        public void SetCommaSeparatedValues(string key, params string[] values)\n        {\n            OwinHelpers.SetHeaderJoined(Store, key, values);\n        }\n\n        /// <summary>\n        /// Adds the given header and values to the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header values.</param>\n        public void Add(string key, string[] value)\n        {\n            Store.Add(key, value);\n        }\n\n        /// <summary>\n        /// Determines whether the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key.\n        /// </summary>\n        /// <param name=\"key\">The key.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains a specific key; otherwise, false.</returns>\n        public bool ContainsKey(string key)\n        {\n            return Store.ContainsKey(key);\n        }\n\n        /// <summary>\n        /// Removes the given header from the collection.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(string key)\n        {\n            return Store.Remove(key);\n        }\n\n        /// <summary>\n        /// Retrieves a value from the dictionary.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The value.</param>\n        /// <returns>true if the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> contains the key; otherwise, false.</returns>\n        public bool TryGetValue(string key, out string[] value)\n        {\n            return Store.TryGetValue(key, out value);\n        }\n\n        /// <summary>\n        /// Adds a new list of items to the collection.\n        /// </summary>\n        /// <param name=\"item\">The item to add.</param>\n        public void Add(KeyValuePair<string, string[]> item)\n        {\n            Store.Add(item);\n        }\n\n        /// <summary>\n        /// Clears the entire list of objects.\n        /// </summary>\n        public void Clear()\n        {\n            Store.Clear();\n        }\n\n        /// <summary>\n        /// Returns a value indicating whether the specified object occurs within this collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object occurs within this collection; otherwise, false.</returns>\n        public bool Contains(KeyValuePair<string, string[]> item)\n        {\n            return Store.Contains(item);\n        }\n\n        /// <summary>\n        /// Copies the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" /> elements to a one-dimensional Array instance at the specified index.\n        /// </summary>\n        /// <param name=\"array\">The one-dimensional Array that is the destination of the specified objects copied from the <see cref=\"T:Microsoft.Owin.HeaderDictionary\" />.</param>\n        /// <param name=\"arrayIndex\">The zero-based index in <paramref name=\"array\" /> at which copying begins.</param>\n        public void CopyTo(KeyValuePair<string, string[]>[] array, int arrayIndex)\n        {\n            Store.CopyTo(array, arrayIndex);\n        }\n\n        /// <summary>\n        /// Removes the given item from the the collection.\n        /// </summary>\n        /// <param name=\"item\">The item.</param>\n        /// <returns>true if the specified object was removed from the collection; otherwise, false.</returns>\n        public bool Remove(KeyValuePair<string, string[]> item)\n        {\n            return Store.Remove(item);\n        }\n    }\n\n    /// <summary>\n    /// Represents the host portion of a Uri can be used to construct Uri's properly formatted and encoded for use in\n    /// HTTP headers.\n    /// </summary>\n    partial struct HostString : IEquatable<HostString>\n    {\n        private readonly string _value;\n\n        /// <summary>\n        /// Creates a new HostString without modification. The value should be Unicode rather than punycode, and may have a port.\n        /// IPv4 and IPv6 addresses are also allowed, and also may have ports.\n        /// </summary>\n        /// <param name=\"value\"></param>\n        public HostString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Returns the original value from the constructor.\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// Returns the value as normalized by ToUriComponent().\n        /// </summary>\n        /// <returns></returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Returns the value properly formatted and encoded for use in a URI in a HTTP header.\n        /// Any Unicode is converted to punycode. IPv6 addresses will have brackets added if they are missing.\n        /// </summary>\n        /// <returns></returns>\n        public string ToUriComponent()\n        {\n            int index;\n            if (string.IsNullOrEmpty(_value))\n            {\n                return string.Empty;\n            }\n            else if (_value.IndexOf('[') >= 0)\n            {\n                // IPv6 in brackets [::1], maybe with port\n                return _value;\n            }\n            else if ((index = _value.IndexOf(':')) >= 0\n                && index < _value.Length - 1\n                && _value.IndexOf(':', index + 1) >= 0)\n            {\n                // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                return \"[\" + _value + \"]\";\n            }\n            else if (index >= 0)\n            {\n                // Has a port\n                string port = _value.Substring(index);\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value, 0, index) + port;\n            }\n            else\n            {\n                var mapping = new IdnMapping();\n                return mapping.GetAscii(_value);\n            }\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the given uri component.\n        /// Any punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uriComponent\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(string uriComponent)\n        {\n            if (!string.IsNullOrEmpty(uriComponent))\n            {\n                int index;\n                if (uriComponent.IndexOf('[') >= 0)\n                {\n                    // IPv6 in brackets [::1], maybe with port\n                }\n                else if ((index = uriComponent.IndexOf(':')) >= 0\n                    && index < uriComponent.Length - 1\n                    && uriComponent.IndexOf(':', index + 1) >= 0)\n                {\n                    // IPv6 without brackets ::1 is the only type of host with 2 or more colons\n                }\n                else if (uriComponent.IndexOf(\"xn--\", StringComparison.Ordinal) >= 0)\n                {\n                    // Contains punycode\n                    if (index >= 0)\n                    {\n                        // Has a port\n                        string port = uriComponent.Substring(index);\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent, 0, index) + port;\n                    }\n                    else\n                    {\n                        IdnMapping mapping = new IdnMapping();\n                        uriComponent = mapping.GetUnicode(uriComponent);\n                    }\n                }\n            }\n            return new HostString(uriComponent);\n        }\n\n        /// <summary>\n        /// Creates a new HostString from the host and port of the give Uri instance.\n        /// Punycode will be converted to Unicode.\n        /// </summary>\n        /// <param name=\"uri\"></param>\n        /// <returns></returns>\n        public static HostString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new HostString(uri.GetComponents(\n                UriComponents.NormalizedHost | // Always convert punycode to Unicode.\n                UriComponents.HostAndPort, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Compares the equality of the Value property, ignoring case.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(HostString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares against the given object only if it is a HostString.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is HostString && Equals((HostString)obj);\n        }\n\n        /// <summary>\n        /// Gets a hash code for the value.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(HostString left, HostString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(HostString left, HostString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Contains the parsed form values.\n    /// </summary>\n    partial interface IFormCollection : IReadableStringCollection\n    {}\n\n    /// <summary>\n    /// Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders.\n    /// </summary>\n    partial interface IHeaderDictionary : IReadableStringCollection, IDictionary<string, string[]>\n    {\n        /// <summary>\n        /// Get or sets the associated value from the collection as a single string.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated value from the collection as a single string or null if the key is not present.</returns>\n        new string this[string key] { get; set; }\n\n        /// <summary>\n        /// Get the associated values from the collection separated into individual values.\n        /// Quoted values will not be split, and the quotes will be removed.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <returns>the associated values from the collection separated into individual values, or null if the key is not present.</returns>\n        IList<string> GetCommaSeparatedValues(string key);\n\n        /// <summary>\n        /// Add a new value. Appends to the header if already present\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Append(string key, string value);\n\n        /// <summary>\n        /// Add new values. Each item remains a separate array entry.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values with any existing values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void AppendCommaSeparatedValues(string key, params string[] values);\n\n        /// <summary>\n        /// Sets a specific header value.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"value\">The header value.</param>\n        void Set(string key, string value);\n\n        /// <summary>\n        /// Sets the specified header values without modification.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetValues(string key, params string[] values);\n\n        /// <summary>\n        /// Quotes any values containing comas, and then coma joins all of the values.\n        /// </summary>\n        /// <param name=\"key\">The header name.</param>\n        /// <param name=\"values\">The header values.</param>\n        void SetCommaSeparatedValues(string key, params string[] values);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinContext\n    {\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        IOwinRequest Request { get; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        IOwinResponse Response { get; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        TextWriter TraceOutput { get; set; }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinContext Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinRequest\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        string Method { get; set; }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        string Scheme { get; set; }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        bool IsSecure { get; }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        HostString Host { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        PathString PathBase { get; set; }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        PathString Path { get; set; }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        QueryString QueryString { get; set; }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        IReadableStringCollection Query { get; }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        Uri Uri { get; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        RequestCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        string CacheControl { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        string MediaType { get; set; }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        string Accept { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        CancellationToken CallCancelled { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        string LocalIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        int? LocalPort { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        string RemoteIpAddress { get; set; }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        int? RemotePort { get; set; }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        ClaimsPrincipal User { get; set; }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        Task<IFormCollection> ReadFormAsync();\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinRequest Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial interface IOwinResponse\n    {\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        IDictionary<string, object> Environment { get; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        IOwinContext Context { get; }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        int StatusCode { get; set; }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        string ReasonPhrase { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        string Protocol { get; set; }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        IHeaderDictionary Headers { get; }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        ResponseCookieCollection Cookies { get; }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        long? ContentLength { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        string ContentType { get; set; }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        DateTimeOffset? Expires { get; set; }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        string ETag { get; set; }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        Stream Body { get; set; }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        void OnSendingHeaders(Action<object> callback, object state);\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        void Redirect(string location);\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        void Write(string text);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        void Write(byte[] data);\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        void Write(byte[] data, int offset, int count);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text);\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(string text, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, CancellationToken token);\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        Task WriteAsync(byte[] data, int offset, int count, CancellationToken token);\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        T Get<T>(string key);\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        IOwinResponse Set<T>(string key, T value);\n    }\n\n    /// <summary>\n    /// Accessors for headers, query, forms, etc.\n    /// </summary>\n    partial interface IReadableStringCollection : IEnumerable<KeyValuePair<string, string[]>>\n    {\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string this[string key] { get; }\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        string Get(string key);\n\n        // Joined\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        IList<string> GetValues(string key);\n\n        // Raw\n    }\n\n    internal static class OwinConstants\n    {\n        #region OWIN v1.0.0 - 3.2.1. Request Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string RequestScheme = \"owin.RequestScheme\";\n        public const string RequestMethod = \"owin.RequestMethod\";\n        public const string RequestPathBase = \"owin.RequestPathBase\";\n        public const string RequestPath = \"owin.RequestPath\";\n        public const string RequestQueryString = \"owin.RequestQueryString\";\n        public const string RequestProtocol = \"owin.RequestProtocol\";\n        public const string RequestHeaders = \"owin.RequestHeaders\";\n        public const string RequestBody = \"owin.RequestBody\";\n        public const string RequestUser = \"owin.RequestUser\"; //owin 1.0.1\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.2. Response Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string ResponseStatusCode = \"owin.ResponseStatusCode\";\n        public const string ResponseReasonPhrase = \"owin.ResponseReasonPhrase\";\n        public const string ResponseProtocol = \"owin.ResponseProtocol\";\n        public const string ResponseHeaders = \"owin.ResponseHeaders\";\n        public const string ResponseBody = \"owin.ResponseBody\";\n\n        #endregion\n\n        #region OWIN v1.0.0 - 3.2.3. Other Data\n\n        // http://owin.org/spec/owin-1.0.0.html\n\n        public const string CallCancelled = \"owin.CallCancelled\";\n\n        public const string OwinVersion = \"owin.Version\";\n\n        #endregion\n\n        #region OWIN Keys for IAppBuilder.Properties\n\n        internal static class Builder\n        {\n            public const string AddSignatureConversion = \"builder.AddSignatureConversion\";\n            public const string DefaultApp = \"builder.DefaultApp\";\n        }\n\n        #endregion\n\n        #region OWIN Key Guidelines and Common Keys - 6. Common keys\n\n        // http://owin.org/spec/CommonKeys.html\n\n        internal static class CommonKeys\n        {\n            public const string ClientCertificate = \"ssl.ClientCertificate\";\n            public const string RemoteIpAddress = \"server.RemoteIpAddress\";\n            public const string RemotePort = \"server.RemotePort\";\n            public const string LocalIpAddress = \"server.LocalIpAddress\";\n            public const string LocalPort = \"server.LocalPort\";\n            public const string IsLocal = \"server.IsLocal\";\n            public const string TraceOutput = \"host.TraceOutput\";\n            public const string Addresses = \"host.Addresses\";\n            public const string AppName = \"host.AppName\";\n            public const string Capabilities = \"server.Capabilities\";\n            public const string OnSendingHeaders = \"server.OnSendingHeaders\";\n            public const string OnAppDisposing = \"host.OnAppDisposing\";\n            public const string Scheme = \"scheme\";\n            public const string Host = \"host\";\n            public const string Port = \"port\";\n            public const string Path = \"path\";\n        }\n\n        #endregion\n\n        #region SendFiles v0.3.0\n\n        // http://owin.org/extensions/owin-SendFile-Extension-v0.3.0.htm\n\n        internal static class SendFiles\n        {\n            // 3.1. Startup\n\n            public const string Version = \"sendfile.Version\";\n            public const string Support = \"sendfile.Support\";\n            public const string Concurrency = \"sendfile.Concurrency\";\n\n            // 3.2. Per Request\n\n            public const string SendAsync = \"sendfile.SendAsync\";\n        }\n\n        #endregion\n\n        #region Opaque v0.3.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class OpaqueConstants\n        {\n            // 3.1. Startup\n            public const string Version = \"opaque.Version\";\n\n            // 3.2. Per Request\n            public const string Upgrade = \"opaque.Upgrade\";\n\n            // 5. Consumption\n            public const string Stream = \"opaque.Stream\";\n            // public const string Version = \"opaque.Version\"; // redundant, declared above\n            public const string CallCancelled = \"opaque.CallCancelled\";\n        }\n\n        #endregion\n\n        #region WebSocket v0.4.0\n\n        // http://owin.org/extensions/owin-OpaqueStream-Extension-v0.3.0.htm\n\n        internal static class WebSocket\n        {\n            // 3.1. Startup\n            public const string Version = \"websocket.Version\";\n\n            // 3.2. Per Request\n            public const string Accept = \"websocket.Accept\";\n\n            // 4. Accept\n            public const string SubProtocol = \"websocket.SubProtocol\";\n\n            // 5. Consumption\n            public const string SendAsync = \"websocket.SendAsync\";\n            public const string ReceiveAsync = \"websocket.ReceiveAsync\";\n            public const string CloseAsync = \"websocket.CloseAsync\";\n            // public const string Version = \"websocket.Version\"; // redundant, declared above\n            public const string CallCancelled = \"websocket.CallCancelled\";\n            public const string ClientCloseStatus = \"websocket.ClientCloseStatus\";\n            public const string ClientCloseDescription = \"websocket.ClientCloseDescription\";\n        }\n\n        #endregion\n\n        #region Security v0.1.0\n\n        // http://owin.org/extensions/owin-Security-Extension-v0.1.0.htm\n\n        internal static class Security\n        {\n            // 3.2. Per Request\n\n            public const string User = \"server.User\";\n\n            public const string Authenticate = \"security.Authenticate\";\n\n            // 3.3. Response\n\n            public const string SignIn = \"security.SignIn\";\n\n            public const string SignOut = \"security.SignOut\";\n\n            public const string SignOutProperties = \"security.SignOutProperties\";\n\n            public const string Challenge = \"security.Challenge\";\n        }\n\n        #endregion\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinContext : IOwinContext\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinContext()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Create a new wrapper.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinContext(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n            Request = new OwinRequest(environment);\n            Response = new OwinResponse(environment);\n        }\n\n        /// <summary>\n        /// Gets a wrapper exposing request specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing request specific properties.</returns>\n        public virtual IOwinRequest Request { get; private set; }\n\n        /// <summary>\n        /// Gets a wrapper exposing response specific properties.\n        /// </summary>\n        /// <returns>A wrapper exposing response specific properties.</returns>\n        public virtual IOwinResponse Response { get; private set; }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets or sets the host.TraceOutput environment value.\n        /// </summary>\n        /// <returns>The host.TraceOutput TextWriter.</returns>\n        public virtual TextWriter TraceOutput\n        {\n            get { return Get<TextWriter>(OwinConstants.CommonKeys.TraceOutput); }\n            set { Set<TextWriter>(OwinConstants.CommonKeys.TraceOutput, value); }\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinContext Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinRequest : IOwinRequest\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinRequest()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Create a new environment wrapper exposing request properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinRequest(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP method.\n        /// </summary>\n        /// <returns>The HTTP method.</returns>\n        public virtual string Method\n        {\n            get { return Get<string>(OwinConstants.RequestMethod); }\n            set { Set(OwinConstants.RequestMethod, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the HTTP request scheme from owin.RequestScheme.\n        /// </summary>\n        /// <returns>The HTTP request scheme from owin.RequestScheme.</returns>\n        public virtual string Scheme\n        {\n            get { return Get<string>(OwinConstants.RequestScheme); }\n            set { Set(OwinConstants.RequestScheme, value); }\n        }\n\n        /// <summary>\n        /// Returns true if the owin.RequestScheme is https.\n        /// </summary>\n        /// <returns>true if this request is using https; otherwise, false.</returns>\n        public virtual bool IsSecure\n        {\n            get { return string.Equals(Scheme, Constants.Https, StringComparison.OrdinalIgnoreCase); }\n        }\n\n        /// <summary>\n        /// Gets or set the Host header. May include the port.\n        /// </summary>\n        /// <return>The Host header.</return>\n        public virtual HostString Host\n        {\n            get { return new HostString(OwinHelpers.GetHost(this)); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Host, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestPathBase.\n        /// </summary>\n        /// <returns>The owin.RequestPathBase.</returns>\n        public virtual PathString PathBase\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPathBase)); }\n            set { Set(OwinConstants.RequestPathBase, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the request path from owin.RequestPath.\n        /// </summary>\n        /// <returns>The request path from owin.RequestPath.</returns>\n        public virtual PathString Path\n        {\n            get { return new PathString(Get<string>(OwinConstants.RequestPath)); }\n            set { Set(OwinConstants.RequestPath, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets or set the query string from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query string from owin.RequestQueryString.</returns>\n        public virtual QueryString QueryString\n        {\n            get { return new QueryString(Get<string>(OwinConstants.RequestQueryString)); }\n            set { Set(OwinConstants.RequestQueryString, value.Value); }\n        }\n\n        /// <summary>\n        /// Gets the query value collection parsed from owin.RequestQueryString.\n        /// </summary>\n        /// <returns>The query value collection parsed from owin.RequestQueryString.</returns>\n        public virtual IReadableStringCollection Query\n        {\n            get { return new ReadableStringCollection(OwinHelpers.GetQuery(this)); }\n        }\n\n        /// <summary>\n        /// Gets the uniform resource identifier (URI) associated with the request.\n        /// </summary>\n        /// <returns>The uniform resource identifier (URI) associated with the request.</returns>\n        public virtual Uri Uri\n        {\n            get { return new Uri(Scheme + \"://\" + Host + PathBase + Path + QueryString); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestProtocol.\n        /// </summary>\n        /// <returns>The owin.RequestProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.RequestProtocol); }\n            set { Set(OwinConstants.RequestProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the request headers.\n        /// </summary>\n        /// <returns>The request headers.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.RequestHeaders); }\n        }\n\n        /// <summary>\n        /// Gets the collection of Cookies for this request.\n        /// </summary>\n        /// <returns>The collection of Cookies for this request.</returns>\n        public RequestCookieCollection Cookies\n        {\n            get { return new RequestCookieCollection(OwinHelpers.GetCookies(this)); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Cache-Control header.\n        /// </summary>\n        /// <returns>The Cache-Control header.</returns>\n        public virtual string CacheControl\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.CacheControl); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.CacheControl, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Media-Type header.\n        /// </summary>\n        /// <returns>The Media-Type header.</returns>\n        public virtual string MediaType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.MediaType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.MediaType, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the Accept header.\n        /// </summary>\n        /// <returns>The Accept header.</returns>\n        public virtual string Accept\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Accept); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Accept, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestBody Stream.\n        /// </summary>\n        /// <returns>The owin.RequestBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.RequestBody); }\n            set { Set(OwinConstants.RequestBody, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the cancellation token for the request.\n        /// </summary>\n        /// <returns>The cancellation token for the request.</returns>\n        public virtual CancellationToken CallCancelled\n        {\n            get { return Get<CancellationToken>(OwinConstants.CallCancelled); }\n            set { Set(OwinConstants.CallCancelled, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalIpAddress.\n        /// </summary>\n        /// <returns>The server.LocalIpAddress.</returns>\n        public virtual string LocalIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalIpAddress); }\n            set { Set(OwinConstants.CommonKeys.LocalIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.LocalPort.\n        /// </summary>\n        /// <returns>The server.LocalPort.</returns>\n        public virtual int? LocalPort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(LocalPortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    LocalPortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.LocalPort);\n                }\n            }\n        }\n\n        private string LocalPortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.LocalPort); }\n            set { Set(OwinConstants.CommonKeys.LocalPort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemoteIpAddress.\n        /// </summary>\n        /// <returns>The server.RemoteIpAddress.</returns>\n        public virtual string RemoteIpAddress\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemoteIpAddress); }\n            set { Set(OwinConstants.CommonKeys.RemoteIpAddress, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the server.RemotePort.\n        /// </summary>\n        /// <returns>The server.RemotePort.</returns>\n        public virtual int? RemotePort\n        {\n            get\n            {\n                int value;\n                if (int.TryParse(RemotePortString, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    RemotePortString = value.Value.ToString(CultureInfo.InvariantCulture);\n                }\n                else\n                {\n                    Environment.Remove(OwinConstants.CommonKeys.RemotePort);\n                }\n            }\n        }\n\n        private string RemotePortString\n        {\n            get { return Get<string>(OwinConstants.CommonKeys.RemotePort); }\n            set { Set(OwinConstants.CommonKeys.RemotePort, value); }\n        }\n\n        /// <summary>\n        /// Gets or set the owin.RequestUser (or gets server.User for non-standard implementations).\n        /// </summary>\n        /// <returns>The server.User.</returns>\n        public virtual ClaimsPrincipal User\n        {\n            get\n            {\n                var claimsPrincipal = Get<ClaimsPrincipal>(OwinConstants.RequestUser);\n                return claimsPrincipal ?? Get<IPrincipal>(OwinConstants.Security.User) as ClaimsPrincipal;\n            }\n            set { Set(OwinConstants.RequestUser, value); }\n        }\n\n        /// <summary>\n        /// Asynchronously reads and parses the request body as a form.\n        /// </summary>\n        /// <returns>The parsed form data.</returns>\n        public async Task<IFormCollection> ReadFormAsync()\n        {\n            var form = Get<IFormCollection>(\"Microsoft.Owin.Form#collection\");\n            if (form == null)\n            {\n                string text;\n                // Don't close, it prevents re-winding.\n                using (var reader = new StreamReader(Body, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: 4 * 1024, leaveOpen: true))\n                {\n                    text = await reader.ReadToEndAsync();\n                }\n                form = OwinHelpers.GetForm(text);\n                Set(\"Microsoft.Owin.Form#collection\", form);\n            }\n\n            return form;\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : default(T);\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinRequest Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// This wraps OWIN environment dictionary and provides strongly typed accessors.\n    /// </summary>\n    partial class OwinResponse : IOwinResponse\n    {\n        /// <summary>\n        /// Create a new context with only request and response header collections.\n        /// </summary>\n        public OwinResponse()\n        {\n            IDictionary<string, object> environment = new Dictionary<string, object>(StringComparer.Ordinal);\n            environment[OwinConstants.RequestHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            environment[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Creates a new environment wrapper exposing response properties.\n        /// </summary>\n        /// <param name=\"environment\">OWIN environment dictionary which stores state information about the request, response and relevant server state.</param>\n        public OwinResponse(IDictionary<string, object> environment)\n        {\n            if (environment == null)\n            {\n                throw new ArgumentNullException(\"environment\");\n            }\n\n            Environment = environment;\n        }\n\n        /// <summary>\n        /// Gets the OWIN environment.\n        /// </summary>\n        /// <returns>The OWIN environment.</returns>\n        public virtual IDictionary<string, object> Environment { get; private set; }\n\n        /// <summary>\n        /// Gets the request context.\n        /// </summary>\n        /// <returns>The request context.</returns>\n        public virtual IOwinContext Context\n        {\n            get { return new OwinContext(Environment); }\n        }\n\n        /// <summary>\n        /// Gets or sets the optional owin.ResponseStatusCode.\n        /// </summary>\n        /// <returns>The optional owin.ResponseStatusCode, or 200 if not set.</returns>\n        public virtual int StatusCode\n        {\n            get { return Get<int>(OwinConstants.ResponseStatusCode, 200); }\n            set { Set(OwinConstants.ResponseStatusCode, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the the optional owin.ResponseReasonPhrase.\n        /// </summary>\n        /// <returns>The the optional owin.ResponseReasonPhrase.</returns>\n        public virtual string ReasonPhrase\n        {\n            get { return Get<string>(OwinConstants.ResponseReasonPhrase); }\n            set { Set(OwinConstants.ResponseReasonPhrase, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseProtocol.\n        /// </summary>\n        /// <returns>The owin.ResponseProtocol.</returns>\n        public virtual string Protocol\n        {\n            get { return Get<string>(OwinConstants.ResponseProtocol); }\n            set { Set(OwinConstants.ResponseProtocol, value); }\n        }\n\n        /// <summary>\n        /// Gets the response header collection.\n        /// </summary>\n        /// <returns>The response header collection.</returns>\n        public virtual IHeaderDictionary Headers\n        {\n            get { return new HeaderDictionary(RawHeaders); }\n        }\n\n        private IDictionary<string, string[]> RawHeaders\n        {\n            get { return Get<IDictionary<string, string[]>>(OwinConstants.ResponseHeaders); }\n        }\n\n        /// <summary>\n        /// Gets a collection used to manipulate the Set-Cookie header.\n        /// </summary>\n        /// <returns>A collection used to manipulate the Set-Cookie header.</returns>\n        public virtual ResponseCookieCollection Cookies\n        {\n            get { return new ResponseCookieCollection(Headers); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Length header.\n        /// </summary>\n        /// <returns>The Content-Length header.</returns>\n        public virtual long? ContentLength\n        {\n            get\n            {\n                long value;\n                if (long.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentLength), out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentLength,\n                        value.Value.ToString(CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.ContentLength);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the Content-Type header.\n        /// </summary>\n        /// <returns>The Content-Type header.</returns>\n        public virtual string ContentType\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ContentType); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ContentType, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the Expires header.\n        /// </summary>\n        /// <returns>The Expires header.</returns>\n        public virtual DateTimeOffset? Expires\n        {\n            get\n            {\n                DateTimeOffset value;\n                if (DateTimeOffset.TryParse(OwinHelpers.GetHeader(RawHeaders, Constants.Headers.Expires),\n                    CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out value))\n                {\n                    return value;\n                }\n                return null;\n            }\n            set\n            {\n                if (value.HasValue)\n                {\n                    OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Expires,\n                        value.Value.ToString(Constants.HttpDateFormat, CultureInfo.InvariantCulture));\n                }\n                else\n                {\n                    RawHeaders.Remove(Constants.Headers.Expires);\n                }\n            }\n        }\n\n        /// <summary>\n        /// Gets or sets the E-Tag header.\n        /// </summary>\n        /// <returns>The E-Tag header.</returns>\n        public virtual string ETag\n        {\n            get { return OwinHelpers.GetHeader(RawHeaders, Constants.Headers.ETag); }\n            set { OwinHelpers.SetHeader(RawHeaders, Constants.Headers.ETag, value); }\n        }\n\n        /// <summary>\n        /// Gets or sets the owin.ResponseBody Stream.\n        /// </summary>\n        /// <returns>The owin.ResponseBody Stream.</returns>\n        public virtual Stream Body\n        {\n            get { return Get<Stream>(OwinConstants.ResponseBody); }\n            set { Set(OwinConstants.ResponseBody, value); }\n        }\n\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public virtual void OnSendingHeaders(Action<object> callback, object state)\n        {\n            var onSendingHeaders = Get<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);\n            if (onSendingHeaders == null)\n            {\n                throw new NotSupportedException(Resources.Exception_MissingOnSendingHeaders);\n            }\n            onSendingHeaders(callback, state);\n        }\n\n        /// <summary>\n        /// Sets a 302 response status code and the Location header.\n        /// </summary>\n        /// <param name=\"location\">The location where to redirect the client.</param>\n        public virtual void Redirect(string location)\n        {\n            StatusCode = 302;\n            OwinHelpers.SetHeader(RawHeaders, Constants.Headers.Location, location);\n        }\n\n        /// <summary>\n        /// Writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        public virtual void Write(string text)\n        {\n            Write(Encoding.UTF8.GetBytes(text));\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        public virtual void Write(byte[] data)\n        {\n            Write(data, 0, data == null ? 0 : data.Length);\n        }\n\n        /// <summary>\n        /// Writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        public virtual void Write(byte[] data, int offset, int count)\n        {\n            Body.Write(data, offset, count);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text)\n        {\n            return WriteAsync(text, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given text to the response body stream using UTF-8.\n        /// </summary>\n        /// <param name=\"text\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(string text, CancellationToken token)\n        {\n            return WriteAsync(Encoding.UTF8.GetBytes(text), token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data)\n        {\n            return WriteAsync(data, CancellationToken.None);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, CancellationToken token)\n        {\n            return WriteAsync(data, 0, data == null ? 0 : data.Length, token);\n        }\n\n        /// <summary>\n        /// Asynchronously writes the given bytes to the response body stream.\n        /// </summary>\n        /// <param name=\"data\">The response data.</param>\n        /// <param name=\"offset\">The zero-based byte offset in the <paramref name=\"data\" /> parameter at which to begin copying bytes.</param>\n        /// <param name=\"count\">The number of bytes to write.</param>\n        /// <param name=\"token\">A token used to indicate cancellation.</param>\n        /// <returns>A Task tracking the state of the write operation.</returns>\n        public virtual Task WriteAsync(byte[] data, int offset, int count, CancellationToken token)\n        {\n            return Body.WriteAsync(data, offset, count, token);\n        }\n\n        /// <summary>\n        /// Gets a value from the OWIN environment, or returns default(T) if not present.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to get.</param>\n        /// <returns>The value with the specified key or the default(T) if not present.</returns>\n        public virtual T Get<T>(string key)\n        {\n            return Get(key, default(T));\n        }\n\n        private T Get<T>(string key, T fallback)\n        {\n            object value;\n            return Environment.TryGetValue(key, out value) ? (T)value : fallback;\n        }\n\n        /// <summary>\n        /// Sets the given key and value in the OWIN environment.\n        /// </summary>\n        /// <typeparam name=\"T\">The type of the value.</typeparam>\n        /// <param name=\"key\">The key of the value to set.</param>\n        /// <param name=\"value\">The value to set.</param>\n        /// <returns>This instance.</returns>\n        public virtual IOwinResponse Set<T>(string key, T value)\n        {\n            Environment[key] = value;\n            return this;\n        }\n    }\n\n    /// <summary>\n    /// Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct PathString : IEquatable<PathString>\n    {\n        private static readonly Func<string, string> EscapeDataString = Uri.EscapeDataString;\n\n        /// <summary>\n        /// Represents the empty path. This field is read-only.\n        /// </summary>\n        public static readonly PathString Empty = new PathString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initialize the path string with a given value. This value must be in un-escaped format. Use\n        /// PathString.FromUriComponent(value) if you have a path value which is in an escaped format.\n        /// </summary>\n        /// <param name=\"value\">The unescaped path to be assigned to the Value property.</param>\n        public PathString(string value)\n        {\n            if (!String.IsNullOrEmpty(value) && value[0] != '/')\n            {\n                throw new ArgumentException(Resources.Exception_PathMustStartWithSlash, \"value\");\n            }\n            _value = value;\n        }\n\n        /// <summary>\n        /// The unescaped path value\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the path is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrEmpty(_value); }\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the path string escaped in a way which is correct for combining into the URI representation.\n        /// </summary>\n        /// <returns>The escaped path value</returns>\n        public string ToUriComponent()\n        {\n            if (HasValue)\n            {\n                if (RequiresEscaping(_value))\n                {\n                    // TODO: Measure the cost of this escaping and consider optimizing.\n                    return String.Join(\"/\", _value.Split('/').Select(EscapeDataString));\n                }\n                return _value;\n            }\n            return String.Empty;\n        }\n\n        // Very conservative, these characters do not need to be escaped in a path.\n        private static bool RequiresEscaping(string value)\n        {\n            for (int i = 0; i < value.Length; i++)\n            {\n                char c = value[i];\n                // Check conservatively for safe characters. See http://www.ietf.org/rfc/rfc3986.txt\n                bool safeChar =\n                    (('a' <= c && c <= 'z')\n                    || ('A' <= c && c <= 'Z')\n                    || ('0' <= c && c <= '9')\n                    || c == '/' || c == '-' || c == '_');\n                if (!safeChar)\n                {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a path.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped path as it appears in the URI format.</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(string uriComponent)\n        {\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(Uri.UnescapeDataString(uriComponent));\n        }\n\n        /// <summary>\n        /// Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting PathString</returns>\n        public static PathString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            // REVIEW: what is the exactly correct thing to do?\n            return new PathString(\"/\" + uri.GetComponents(UriComponents.Path, UriFormat.Unescaped));\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                return value1.Length == value2.Length || value1[value2.Length] == '/';\n            }\n            return false;\n        }\n\n        /// <summary>\n        /// Checks if this instance starts with or exactly matches the other instance. Only full segments are matched.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <param name=\"remaining\">Any remaining segments from this instance not included in the other instance.</param>\n        /// <returns></returns>\n        public bool StartsWithSegments(PathString other, out PathString remaining)\n        {\n            string value1 = Value ?? String.Empty;\n            string value2 = other.Value ?? String.Empty;\n            if (value1.StartsWith(value2, StringComparison.OrdinalIgnoreCase))\n            {\n                if (value1.Length == value2.Length || value1[value2.Length] == '/')\n                {\n                    remaining = new PathString(value1.Substring(value2.Length));\n                    return true;\n                }\n            }\n            remaining = Empty;\n            return false;\n        }\n\n        /// <summary>\n        /// Adds two PathString instances into a combined PathString value.\n        /// </summary>\n        /// <returns>The combined PathString value</returns>\n        public PathString Add(PathString other)\n        {\n            return new PathString(Value + other.Value);\n        }\n\n        /// <summary>\n        /// Combines a PathString and QueryString into the joined URI formatted string value.\n        /// </summary>\n        /// <returns>The joined URI formatted string value</returns>\n        public string Add(QueryString other)\n        {\n            return ToUriComponent() + other.ToUriComponent();\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other)\n        {\n            return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value using a specific StringComparison type\n        /// </summary>\n        /// <param name=\"other\">The second PathString for comparison</param>\n        /// <param name=\"comparisonType\">The StringComparison type to use</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public bool Equals(PathString other, StringComparison comparisonType)\n        {\n            return string.Equals(_value, other._value, comparisonType);\n        }\n\n        /// <summary>\n        /// Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase.\n        /// </summary>\n        /// <param name=\"obj\">The second PathString for comparison.</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is PathString && Equals((PathString)obj, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation.\n        /// </summary>\n        /// <returns>The hash code</returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are equal</returns>\n        public static bool operator ==(PathString left, PathString right)\n        {\n            return left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Equals\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>True if both PathString values are not equal</returns>\n        public static bool operator !=(PathString left, PathString right)\n        {\n            return !left.Equals(right, StringComparison.OrdinalIgnoreCase);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static PathString operator +(PathString left, PathString right)\n        {\n            return left.Add(right);\n        }\n\n        /// <summary>\n        /// Operator call through to Add\n        /// </summary>\n        /// <param name=\"left\">The left parameter</param>\n        /// <param name=\"right\">The right parameter</param>\n        /// <returns>The PathString combination of both values</returns>\n        public static string operator +(PathString left, QueryString right)\n        {\n            return left.Add(right);\n        }\n    }\n\n    /// <summary>\n    /// Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string\n    /// </summary>\n    partial struct QueryString : IEquatable<QueryString>\n    {\n        /// <summary>\n        /// Represents the empty query string. This field is read-only.\n        /// </summary>\n        public static readonly QueryString Empty = new QueryString(String.Empty);\n\n        private readonly string _value;\n\n        /// <summary>\n        /// Initalize the query string with a given value. This value must be in escaped and delimited format without\n        /// a leading '?' character.\n        /// </summary>\n        /// <param name=\"value\">The query string to be assigned to the Value property.</param>\n        public QueryString(string value)\n        {\n            _value = value;\n        }\n\n        /// <summary>\n        /// Initialize a query string with a single given parameter name and value. The value is\n        /// </summary>\n        /// <param name=\"name\">The unencoded parameter name</param>\n        /// <param name=\"value\">The unencoded parameter value</param>\n        public QueryString(string name, string value)\n        {\n            _value = Uri.EscapeDataString(name) + '=' + Uri.EscapeDataString(value);\n        }\n\n        /// <summary>\n        /// The unescaped query string without the leading '?' character\n        /// </summary>\n        public string Value\n        {\n            get { return _value; }\n        }\n\n        /// <summary>\n        /// True if the query string is not empty\n        /// </summary>\n        public bool HasValue\n        {\n            get { return !String.IsNullOrWhiteSpace(_value); }\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentally\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public override string ToString()\n        {\n            return ToUriComponent();\n        }\n\n        /// <summary>\n        /// Provides the query string escaped in a way which is correct for combining into the URI representation.\n        /// A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially\n        /// dangerous are escaped.\n        /// </summary>\n        /// <returns>The query string value</returns>\n        public string ToUriComponent()\n        {\n            // Escape things properly so System.Uri doesn't mis-interpret the data.\n            return HasValue ? \"?\" + _value.Replace(\"#\", \"%23\") : String.Empty;\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any\n        /// value that is not a query.\n        /// </summary>\n        /// <param name=\"uriComponent\">The escaped query as it appears in the URI format.</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(string uriComponent)\n        {\n            if (String.IsNullOrEmpty(uriComponent))\n            {\n                return new QueryString(string.Empty);\n            }\n            if (uriComponent[0] != '?')\n            {\n                throw new ArgumentException(Resources.Exception_QueryStringMustStartWithDelimiter, \"uriComponent\");\n            }\n            return new QueryString(uriComponent.Substring(1));\n        }\n\n        /// <summary>\n        /// Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported.\n        /// </summary>\n        /// <param name=\"uri\">The Uri object</param>\n        /// <returns>The resulting QueryString</returns>\n        public static QueryString FromUriComponent(Uri uri)\n        {\n            if (uri == null)\n            {\n                throw new ArgumentNullException(\"uri\");\n            }\n            return new QueryString(uri.GetComponents(UriComponents.Query, UriFormat.UriEscaped));\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"other\"></param>\n        /// <returns></returns>\n        public bool Equals(QueryString other)\n        {\n            return string.Equals(_value, other._value);\n        }\n\n        /// <summary>\n        /// Indicates whether the current instance is equal to the other instance.\n        /// </summary>\n        /// <param name=\"obj\"></param>\n        /// <returns></returns>\n        public override bool Equals(object obj)\n        {\n            if (ReferenceEquals(null, obj))\n            {\n                return false;\n            }\n            return obj is QueryString && Equals((QueryString)obj);\n        }\n\n        /// <summary>\n        /// Returns the hash code for this instance.\n        /// </summary>\n        /// <returns></returns>\n        public override int GetHashCode()\n        {\n            return (_value != null ? _value.GetHashCode() : 0);\n        }\n\n        /// <summary>\n        /// Compares the two instances for equality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator ==(QueryString left, QueryString right)\n        {\n            return left.Equals(right);\n        }\n\n        /// <summary>\n        /// Compares the two instances for inequality.\n        /// </summary>\n        /// <param name=\"left\"></param>\n        /// <param name=\"right\"></param>\n        /// <returns></returns>\n        public static bool operator !=(QueryString left, QueryString right)\n        {\n            return !left.Equals(right);\n        }\n    }\n\n    /// <summary>\n    /// Accessors for query, forms, etc.\n    /// </summary>\n    partial class ReadableStringCollection : IReadableStringCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public ReadableStringCollection(IDictionary<string, string[]> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string[]> Store { get; set; }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get { return Get(key); }\n        }\n\n        /// <summary>\n        /// Get the associated value from the collection.  Multiple values will be merged.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string Get(string key)\n        {\n            return OwinHelpers.GetJoinedValue(Store, key);\n        }\n\n        /// <summary>\n        /// Get the associated values from the collection in their original format.\n        /// Returns null if the key is not present.\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public IList<string> GetValues(string key)\n        {\n            string[] values;\n            Store.TryGetValue(key, out values);\n            return values;\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    /// <summary>\n    /// A wrapper for the request Cookie header\n    /// </summary>\n    partial class RequestCookieCollection : IEnumerable<KeyValuePair<string, string>>\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"store\"></param>\n        public RequestCookieCollection(IDictionary<string, string> store)\n        {\n            if (store == null)\n            {\n                throw new ArgumentNullException(\"store\");\n            }\n\n            Store = store;\n        }\n\n        private IDictionary<string, string> Store { get; set; }\n\n        /// <summary>\n        /// Returns null rather than throwing KeyNotFoundException\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <returns></returns>\n        public string this[string key]\n        {\n            get\n            {\n                string value;\n                Store.TryGetValue(key, out value);\n                return value;\n            }\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()\n        {\n            return Store.GetEnumerator();\n        }\n\n        /// <summary>\n        ///\n        /// </summary>\n        /// <returns></returns>\n        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\n        {\n            return GetEnumerator();\n        }\n    }\n\n    internal static class Resources\n    {\n        internal const string Exception_MissingOnSendingHeaders = \"The OWIN key 'server.OnSsoendingHeaders' is not available for this request.\";\n        internal const string Exception_PathMustStartWithSlash = \"The path must start with a '/' followed by one or more characters.\";\n        internal const string Exception_QueryStringMustStartWithDelimiter = \"The query string must start with a '?' unless null or empty.\";\n    }\n\n    /// <summary>\n    /// A wrapper for the response Set-Cookie header\n    /// </summary>\n    partial class ResponseCookieCollection\n    {\n        /// <summary>\n        /// Create a new wrapper\n        /// </summary>\n        /// <param name=\"headers\"></param>\n        public ResponseCookieCollection(IHeaderDictionary headers)\n        {\n            if (headers == null)\n            {\n                throw new ArgumentNullException(\"headers\");\n            }\n\n            Headers = headers;\n        }\n\n        private IHeaderDictionary Headers { get; set; }\n\n        /// <summary>\n        /// Add a new cookie and value\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        public void Append(string key, string value)\n        {\n            Headers.AppendValues(Constants.Headers.SetCookie, Uri.EscapeDataString(key) + \"=\" + Uri.EscapeDataString(value) + \"; path=/\");\n        }\n\n        /// <summary>\n        /// Add a new cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"value\"></param>\n        /// <param name=\"options\"></param>\n        public void Append(string key, string value, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n            bool expiresHasValue = options.Expires.HasValue;\n\n            string setCookieValue = string.Concat(\n                Uri.EscapeDataString(key),\n                \"=\",\n                Uri.EscapeDataString(value ?? string.Empty),\n                !domainHasValue ? null : \"; domain=\",\n                !domainHasValue ? null : options.Domain,\n                !pathHasValue ? null : \"; path=\",\n                !pathHasValue ? null : options.Path,\n                !expiresHasValue ? null : \"; expires=\",\n                !expiresHasValue ? null : options.Expires.Value.ToString(\"ddd, dd-MMM-yyyy HH:mm:ss \", CultureInfo.InvariantCulture) + \"GMT\",\n                !options.Secure ? null : \"; secure\",\n                !options.HttpOnly ? null : \"; HttpOnly\");\n            Headers.AppendValues(\"Set-Cookie\", setCookieValue);\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        public void Delete(string key)\n        {\n            Func<string, bool> predicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n\n            var deleteCookies = new[] { Uri.EscapeDataString(key) + \"=; expires=Thu, 01-Jan-1970 00:00:00 GMT\" };\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues == null || existingValues.Count == 0)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, deleteCookies);\n            }\n            else\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !predicate(value)).Concat(deleteCookies).ToArray());\n            }\n        }\n\n        /// <summary>\n        /// Sets an expired cookie\n        /// </summary>\n        /// <param name=\"key\"></param>\n        /// <param name=\"options\"></param>\n        public void Delete(string key, CookieOptions options)\n        {\n            if (options == null)\n            {\n                throw new ArgumentNullException(\"options\");\n            }\n\n            bool domainHasValue = !string.IsNullOrEmpty(options.Domain);\n            bool pathHasValue = !string.IsNullOrEmpty(options.Path);\n\n            Func<string, bool> rejectPredicate;\n            if (domainHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"domain=\" + options.Domain, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else if (pathHasValue)\n            {\n                rejectPredicate = value =>\n                    value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase) &&\n                        value.IndexOf(\"path=\" + options.Path, StringComparison.OrdinalIgnoreCase) != -1;\n            }\n            else\n            {\n                rejectPredicate = value => value.StartsWith(key + \"=\", StringComparison.OrdinalIgnoreCase);\n            }\n\n            IList<string> existingValues = Headers.GetValues(Constants.Headers.SetCookie);\n            if (existingValues != null)\n            {\n                Headers.SetValues(Constants.Headers.SetCookie, existingValues.Where(value => !rejectPredicate(value)).ToArray());\n            }\n\n            Append(key, string.Empty, new CookieOptions\n            {\n                Path = options.Path,\n                Domain = options.Domain,\n                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),\n            });\n        }\n    }\n\n\n    static partial class IOwinResponseExtension \n    {\n        /// <summary>\n        /// Registers for an event that fires when the response headers are sent.\n        /// </summary>\n        /// <param name=\"response\">The owin response</param>\n        /// <param name=\"callback\">The callback method.</param>\n        /// <param name=\"state\">The callback state.</param>\n        public static void OnSendingHeaders<T>(this IOwinResponse response, Action<T> callback, T state)\n        {\n            if (response == null) {\n                throw new ArgumentNullException(\"response\");\n            }\n            Action<object> innerCallback = innerState => callback((T)innerState);\n            response.OnSendingHeaders(innerCallback, state);\n        }\n        \n    }\n}\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/Bootstrapper.cs",
    "content": "namespace LoyaltyProgram\n{\n  using System;\n  using System.Collections.Generic;\n  using System.Security.Claims;\n  using Nancy;\n  using Nancy.Bootstrapper;\n  using Nancy.TinyIoc;\n  using Nancy.Owin;\n\n  public class Bootstrapper : DefaultNancyBootstrapper\n  {\n    protected override Func<ITypeCatalog, NancyInternalConfiguration> InternalConfiguration\n     => NancyInternalConfiguration.WithOverrides(builder => builder.StatusCodeHandlers.Clear());\n\n    protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)\n    {\n      pipelines.OnError += (ctx, ex) =>\n      {\n        // write to central log store\n        return null;\n      };\n    }\n  }\n\n  public class SetUser : IRequestStartup\n  {\n    public void Initialize(IPipelines pipelines, NancyContext context) =>\n      context.CurrentUser = context.GetOwinEnvironment()[\"pos-end-user\"] as ClaimsPrincipal;\n  }\n}\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/Dockerfile",
    "content": "FROM microsoft/aspnet:1.0.0-rc1-update1\n\nRUN printf \"deb http://ftp.us.debian.org/debian jessie main\\n\" >> /etc/apt/sources.list\nRUN apt-get -qq update && apt-get install -qqy sqlite3 libsqlite3-dev && rm -rf /var/lib/apt/lists/*\n\nCOPY . /app\nWORKDIR /app\nRUN [\"dnu\", \"restore\"]\n\nEXPOSE 5000/tcp\nENTRYPOINT [\"dnx\", \"-p\", \"project.json\", \"Microsoft.AspNet.Server.Kestrel\", \"--server.urls\", \"http://0.0.0.0:5000\"]\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/LoyaltyProgram.xproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <VisualStudioVersion Condition=\"'$(VisualStudioVersion)' == ''\">14.0</VisualStudioVersion>\n    <VSToolsPath Condition=\"'$(VSToolsPath)' == ''\">$(MSBuildExtensionsPath32)\\Microsoft\\VisualStudio\\v$(VisualStudioVersion)</VSToolsPath>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet\\Microsoft.DotNet.Props\" Condition=\"'$(VSToolsPath)' != ''\" />\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>4bed3c45-e8c3-4345-a08f-249a39a256eb</ProjectGuid>\n    <RootNamespace>LoyaltyProgram</RootNamespace>\n    <BaseIntermediateOutputPath Condition=\"'$(BaseIntermediateOutputPath)'=='' \">.\\obj</BaseIntermediateOutputPath>\n    <OutputPath Condition=\"'$(OutputPath)'=='' \">.\\bin\\</OutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup>\n    <SchemaVersion>2.0</SchemaVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VSToolsPath)\\DotNet.Web\\Microsoft.DotNet.Web.targets\" Condition=\"'$(VSToolsPath)' != ''\" />\n</Project>"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/Program.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace LoyaltyProgram\n{\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            var host = new WebHostBuilder()\n                .UseKestrel()\n                .UseContentRoot(Directory.GetCurrentDirectory())\n                .UseIISIntegration()\n                .UseStartup<Startup>()\n                .Build();\n\n            host.Run();\n        }\n    }\n}\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/Properties/launchSettings.json",
    "content": "{\n  \"iisSettings\": {\n    \"windowsAuthentication\": false,\n    \"anonymousAuthentication\": true,\n    \"iisExpress\": {\n      \"applicationUrl\": \"http://localhost:55343/\",\n      \"sslPort\": 0\n    }\n  },\n  \"profiles\": {\n    \"IIS Express\": {\n      \"commandName\": \"IISExpress\",\n      \"launchBrowser\": true,\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    },\n    \"LoyaltyProgram\": {\n      \"commandName\": \"Project\",\n      \"launchBrowser\": true,\n      \"launchUrl\": \"http://localhost:5000\",\n      \"environmentVariables\": {\n        \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/README.md",
    "content": "# Welcome to ASP.NET Core\n\nWe've made some big updates in this release, so it’s **important** that you spend a few minutes to learn what’s new.\n\nYou've created a new ASP.NET Core project. [Learn what's new](https://go.microsoft.com/fwlink/?LinkId=518016)\n\n## This application consists of:\n\n*   Sample pages using ASP.NET Core MVC\n*   [Gulp](https://go.microsoft.com/fwlink/?LinkId=518007) and [Bower](https://go.microsoft.com/fwlink/?LinkId=518004) for managing client-side libraries\n*   Theming using [Bootstrap](https://go.microsoft.com/fwlink/?LinkID=398939)\n\n## How to\n\n*   [Add a Controller and View](https://go.microsoft.com/fwlink/?LinkID=398600)\n*   [Add an appsetting in config and access it in app.](https://go.microsoft.com/fwlink/?LinkID=699562)\n*   [Manage User Secrets using Secret Manager.](https://go.microsoft.com/fwlink/?LinkId=699315)\n*   [Use logging to log a message.](https://go.microsoft.com/fwlink/?LinkId=699316)\n*   [Add packages using NuGet.](https://go.microsoft.com/fwlink/?LinkId=699317)\n*   [Add client packages using Bower.](https://go.microsoft.com/fwlink/?LinkId=699318)\n*   [Target development, staging or production environment.](https://go.microsoft.com/fwlink/?LinkId=699319)\n\n## Overview\n\n*   [Conceptual overview of what is ASP.NET Core](https://go.microsoft.com/fwlink/?LinkId=518008)\n*   [Fundamentals of ASP.NET Core such as Startup and middleware.](https://go.microsoft.com/fwlink/?LinkId=699320)\n*   [Working with Data](https://go.microsoft.com/fwlink/?LinkId=398602)\n*   [Security](https://go.microsoft.com/fwlink/?LinkId=398603)\n*   [Client side development](https://go.microsoft.com/fwlink/?LinkID=699321)\n*   [Develop on different platforms](https://go.microsoft.com/fwlink/?LinkID=699322)\n*   [Read more on the documentation site](https://go.microsoft.com/fwlink/?LinkID=699323)\n\n## Run & Deploy\n\n*   [Run your app](https://go.microsoft.com/fwlink/?LinkID=517851)\n*   [Run tools such as EF migrations and more](https://go.microsoft.com/fwlink/?LinkID=517853)\n*   [Publish to Microsoft Azure Web Apps](https://go.microsoft.com/fwlink/?LinkID=398609)\n\nWe would love to hear your [feedback](https://go.microsoft.com/fwlink/?LinkId=518015)\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/Startup.cs",
    "content": "namespace LoyaltyProgram\n{\n  using System.Collections.Generic;\n  using System.IdentityModel.Tokens.Jwt;\n  using System.Text.Encodings.Web;\n  using System.Threading.Tasks;\n  using Microsoft.AspNetCore.Builder;\n  using Microsoft.IdentityModel.Tokens;\n  using LibOwin;\n  using Microsoft.Extensions.DependencyInjection;\n  using Nancy.Owin;\n\n  public class Startup\n  {\n    public void ConfigureServices(IServiceCollection services)\n    {\n      services.AddTransient(provider => UrlEncoder.Default);\n    }\n\n    public void Configure(IApplicationBuilder app)\n    {\n      JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>();\n\n      var options = new JwtBearerOptions\n      {\n        Authority = \"http://localhost:5001\",\n        RequireHttpsMetadata = false,\n        Audience = \"http://localhost:5001/resources\",\n        AutomaticAuthenticate = true\n      };\n      app.UseJwtBearerAuthentication(options);\n\n      app.UseOwin(buildFunc =>\n      {\n        buildFunc(next => env =>\n        {\n          var ctx = new OwinContext(env);\n          var principal = ctx.Request.User;\n          if (principal?.HasClaim(\"scope\", \"loyalty_program_write\") ?? false)\n            return next(env);\n          ctx.Response.StatusCode = 403;\n          return Task.FromResult(0);\n        });\n        buildFunc(next => env =>\n        {\n          var ctx = new OwinContext(env);\n          var idToken = ctx.Request.User?.FindFirst(\"id_token\");\n          if (idToken != null)\n          {\n            ctx.Set(\"pos-end-user-token\", idToken);\n          }\n          return next(env);\n        });\n        buildFunc(next => env =>\n        {\n          var ctx = new OwinContext(env);\n          if (ctx.Request.Headers.ContainsKey(\"pos-end-user\"))\n          {\n            var tokenHandler = new JwtSecurityTokenHandler();\n            SecurityToken token;\n            var userPrincipal =\n              tokenHandler.ValidateToken(ctx.Request.Headers[\"pos-end-user\"],\n                                         new TokenValidationParameters(),\n                                         out token);\n            ctx.Set(\"pos-end-user\", userPrincipal);\n          }\n          return next(env);\n        });\n        buildFunc.UseNancy();\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/UsersModule.cs",
    "content": "namespace LoyaltyProgram\n{\n  using System.Linq;\n  using System.Net;\n  using System.Collections.Generic;\n  using Nancy;\n  using Nancy.ModelBinding;\n\n  using HttpStatusCode = Nancy.HttpStatusCode;\n\n  public class UsersModule : NancyModule\n  {\n    private static IDictionary<int, LoyaltyProgramUser> registeredUsers =\n      new Dictionary<int, LoyaltyProgramUser>();\n\n    public UsersModule() : base(\"/users\")\n    {\n      Get(\"/\", _ => registeredUsers.Values);\n\n      Get(\"/{userId:int}\", parameters =>\n      {\n        int userId = parameters.userId;\n        if (registeredUsers.ContainsKey(userId))\n          return registeredUsers[userId];\n        else\n          return HttpStatusCode.NotFound;\n      });\n\n      Post(\"/\", _ =>\n      {\n        var newUser = this.Bind<LoyaltyProgramUser>();\n        this.AddRegisteredUser(newUser);\n        return this.CreatedResponse(newUser);\n      });\n\n      Put(\"/{userId:int}\", parameters =>\n      {\n        int loggedInUserId;\n        int.TryParse(\n          this.Context\n            .CurrentUser\n            .Claims.FirstOrDefault(c => c.Type.StartsWith(\"id\"))\n            ?.Value.Split(':').Last() ?? \"\",\n          out loggedInUserId);\n        int userId = parameters.userId;\n        if (loggedInUserId != userId)\n          return HttpStatusCode.Forbidden;\n        var updatedUser = this.Bind<LoyaltyProgramUser>();\n        registeredUsers[userId] = updatedUser;\n        return updatedUser;\n      });\n    }\n\n    private dynamic CreatedResponse(LoyaltyProgramUser newUser)\n    {\n      return\n          this.Negotiate\n              .WithStatusCode(HttpStatusCode.Created)\n              .WithHeader(\"Location\", this.Request.Url.SiteBase + \"/users/\" + newUser.Id)\n              .WithModel(newUser);\n    }\n\n    private void AddRegisteredUser(LoyaltyProgramUser newUser)\n    {\n      var userId = registeredUsers.Count;\n      newUser.Id = userId;\n      registeredUsers[userId] = newUser;\n    }\n  }\n\n  public class LoyaltyProgramUser\n  {\n    public int Id { get; set; }\n    public string Name { get; set; }\n    public int LoyaltyPoints { get; set; }\n    public LoyaltyProgramSettings Settings { get; set; }\n  }\n\n  public class LoyaltyProgramSettings\n  {\n    public string[] Interests { get; set; }\n  }\n}\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/YamlSerializerDeserializer.cs",
    "content": "namespace LoyaltyProgram\n{\n   using System;\n   using System.Collections.Generic;\n   using System.IO;\n   using Nancy;\n   using Nancy.ModelBinding;\n   using Nancy.Responses.Negotiation;\n   using YamlDotNet.Serialization;\n\n    public class YamlBodyDeserializer : IBodyDeserializer\n    {\n        public bool CanDeserialize(MediaRange mediaRange, BindingContext context)\n          => mediaRange.Subtype.ToString().EndsWith(\"yaml\");\n\n        public object Deserialize(MediaRange mediaRange, Stream bodyStream, BindingContext context)\n        {\n          var yamlDeserializer = new Deserializer();\n          var reader = new StreamReader(bodyStream);\n          return yamlDeserializer.Deserialize(reader, context.DestinationType);\n        }\n    }\n\n    public class YamlBodySerializer : IResponseProcessor\n    {\n        public IEnumerable<Tuple<string, MediaRange>> ExtensionMappings\n        {\n            get\n            {\n              yield return new Tuple<string, MediaRange>(\"yaml\", new MediaRange(\"application/yaml\"));\n            }\n        }\n\n        public ProcessorMatch CanProcess(MediaRange requestedMediaRange, dynamic model, NancyContext context)\n          =>\n            requestedMediaRange.Subtype.ToString().EndsWith(\"yaml\") \n            ? new ProcessorMatch { ModelResult = MatchResult.DontCare, RequestedContentTypeResult = MatchResult.NonExactMatch}\n            : ProcessorMatch.None;         \n\n        public Response Process(MediaRange requestedMediaRange, dynamic model, NancyContext context)\n          =>\n            new Response\n            {\n              Contents = stream =>\n              {\n                  var yamlSerializer = new Serializer();\n                  var streamWriter = new StreamWriter(stream);\n                  yamlSerializer.Serialize(streamWriter, model);\n                  streamWriter.Flush();\n              },\n              ContentType = \"application/yaml\"\n            };      \n    }\n}"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/project.json",
    "content": "{\n  \"dependencies\": {\n    \"Microsoft.NETCore.App\": {\n      \"version\": \"1.0.0\",\n      \"type\": \"platform\"\n    },\n    \"Microsoft.AspNetCore.Server.IISIntegration\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Server.Kestrel\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Owin\": \"1.0.0\",\n    \"Microsoft.AspNetCore.Authentication.JwtBearer\": \"1.0.0\",\n    \"System.Text.Encodings.Web\": \"4.0.0\",\n    \"Nancy\": \"2.0.0-barneyrubble\",\n    \"YamlDotNet\": \"3.8.0-pre233\"\n  },\n\n  \"tools\": {                                                                  \n    \"Microsoft.AspNetCore.Server.IISIntegration.Tools\": \"1.0.0-preview2-final\"\n  },\n\n  \"frameworks\": {\n    \"netcoreapp1.0\": {\n      \"imports\": [\n        \"dotnet5.6\",\n        \"portable-net45+win8\"\n      ]\n    }\n  },\n\n  \"buildOptions\": {\n    \"emitEntryPoint\": true,\n    \"preserveCompilationContext\": true\n  },\n\n  \"runtimeOptions\": {\n    \"gcServer\": true\n  },\n\n  \"publishOptions\": {\n    \"include\": [\n      \"wwwroot\",\n      \"web.config\"\n    ]\n  },\n\n  \"scripts\": {\n    \"postpublish\": [ \"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%\" ]\n  },\n\n  \"tooling\": {\n    \"defaultNamespace\": \"LoyaltyProgram\"\n  }\n}\n"
  },
  {
    "path": "src/chapter10/LoyaltyProgram/web.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n\n  <!--\n    Configure your application settings in appsettings.json. Learn more at https://go.microsoft.com/fwlink/?LinkId=786380\n  -->\n\n  <system.webServer>\n    <handlers>\n      <add name=\"aspNetCore\" path=\"*\" verb=\"*\" modules=\"AspNetCoreModule\" resourceType=\"Unspecified\"/>\n    </handlers>\n    <aspNetCore processPath=\"%LAUNCHER_PATH%\" arguments=\"%LAUNCHER_ARGS%\" stdoutLogEnabled=\"false\" stdoutLogFile=\".\\logs\\stdout\" forwardWindowsAuthToken=\"false\"/>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "src/chapter10/ch10.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25123.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"LoyaltyProgram\", \"LoyaltyProgram\\LoyaltyProgram.xproj\", \"{4BED3C45-E8C3-4345-A08F-249A39A256EB}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"ApiGatewayMock\", \"ApiGatewayMock\\ApiGatewayMock.xproj\", \"{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}\"\nEndProject\nProject(\"{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}\") = \"Login\", \"Login\\Login.xproj\", \"{F416D0B1-71EE-400E-91E2-FC2B047DA208}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{4BED3C45-E8C3-4345-A08F-249A39A256EB}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{FE109A02-BF1B-46FC-87C8-2A68781CE8A4}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{F416D0B1-71EE-400E-91E2-FC2B047DA208}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{F416D0B1-71EE-400E-91E2-FC2B047DA208}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{F416D0B1-71EE-400E-91E2-FC2B047DA208}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{F416D0B1-71EE-400E-91E2-FC2B047DA208}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/chapter10/start-app.ps1",
    "content": "start-process dotnet -ArgumentList run -WorkingDirectory ./IdentityServer\nstart-process dotnet -ArgumentList run -WorkingDirectory ./LoyaltyProgram\nstart-process dotnet -ArgumentList run -WorkingDirectory ./ApiGatewayMock \n"
  },
  {
    "path": "src/global.json",
    "content": "{\n    \"projects\": [ \"Chapter11\" ],\n    \"sdk\": {\n        \"version\": \"1.0.0-preview2-003121\"\n    }\n}\n"
  }
]