├── .gitattributes ├── .gitignore ├── AutomaticScalingPattern ├── App.config ├── AutomaticScalingPattern.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── CQRSPattern ├── App.config ├── CQRSPattern.csproj ├── DataStores │ ├── CommandDataStore.cs │ └── QueryDataStore.cs ├── Models │ ├── Car.cs │ └── CarDetails.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── Services │ ├── CarCommandService.cs │ ├── CarQueryService.cs │ └── ConsitencyWorker.cs ├── CacheAsidePattern ├── App.config ├── CacheAsidePattern.csproj ├── CacheService.cs ├── FakeDataSource.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── CircuitBreakerPattern ├── CircuitBreaker │ ├── CircuitBreaker.cs │ ├── CircuitBreakerOpenException.cs │ ├── CircuitBreakerStateEnum.cs │ ├── CircuitBreakerStateStore.cs │ └── ICircuitBreakerStateStore.cs ├── CircuitBreakerPattern.csproj ├── ExternalService │ └── ExternalService.cs ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── CloudDesignPatterns.sln ├── EventSourcingPattern ├── App.config ├── Commands │ ├── CashDepositCommand.cs │ └── CashWithdrawalCommand.cs ├── EventSourcingPattern.csproj ├── EventStore │ ├── Command.cs │ └── EventStore.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── QueueBasedLoadLevelingPatternApplication ├── App.config ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── QueueBasedLoadLevelingPatternApplication.csproj ├── QueueBasedLoadLevelingPatternLibary ├── Properties │ └── AssemblyInfo.cs ├── QueueBasedLoadLevelingPatternLibary.csproj ├── QueueService.cs └── packages.config ├── QueueBasedLoadLevelingPatternService ├── App.config ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── QueueBasedLoadLevelingPatternService.csproj └── packages.config ├── QueueBasedLoadLevelingPatternWebJob ├── App.config ├── Functions.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── QueueBasedLoadLevelingPatternWebJob.csproj └── packages.config ├── README.md ├── RetryPattern ├── App.config ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── RetryPattern.csproj ├── StorageService.cs └── packages.config ├── RuntimeReconfigurationPattern ├── .bowerrc ├── Controllers │ └── HomeController.cs ├── Models │ └── AppSettings.cs ├── Program.cs ├── Properties │ ├── PublishProfiles │ │ └── configchanges - Web Deploy.pubxml │ └── launchSettings.json ├── RuntimeReconfigurationPattern.csproj ├── Startup.cs ├── Views │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ └── Index.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── _Layout.cshtml │ │ └── _ValidationScriptsPartial.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── app.config ├── appsettings.Development.json ├── appsettings.json ├── bower.json ├── bundleconfig.json ├── web.config └── wwwroot │ ├── css │ ├── site.css │ └── site.min.css │ ├── favicon.ico │ ├── images │ ├── banner1.svg │ ├── banner2.svg │ ├── banner3.svg │ └── banner4.svg │ ├── js │ ├── site.js │ └── site.min.js │ └── lib │ ├── bootstrap │ ├── .bower.json │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── jquery-validation-unobtrusive │ ├── .bower.json │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── .bower.json │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.js │ │ └── jquery.validate.min.js │ └── jquery │ ├── .bower.json │ ├── LICENSE.txt │ └── dist │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map ├── ShardingPattern ├── App.config ├── InitializeShard.sql ├── LICENSE ├── Program.cs ├── README.txt ├── Samples │ ├── CreateShardSample.cs │ ├── DataDependentRoutingSample.cs │ └── MultiShardQuerySample.cs ├── ShardingPattern.csproj ├── Utils │ ├── Configuration.cs │ ├── ConsoleUtils.cs │ ├── ShardManagementUtils.cs │ ├── SqlDatabaseUtils.cs │ └── TableFormatter.cs └── packages.config ├── The Cloud Design Patterns you didn't know you needed .pdf └── ValetKeyPattern ├── .bowerrc ├── AzureStorage ├── CORSConfigurator.cs └── ICORSConfigurator.cs ├── Controllers ├── HomeController.cs └── SaSController.cs ├── Models ├── AppSettings.cs └── ConnectionStrings.cs ├── Program.cs ├── Properties └── launchSettings.json ├── Startup.cs ├── ValetKeyPattern.csproj ├── Views ├── Home │ ├── About.cshtml │ ├── Contact.cshtml │ ├── Index.cshtml │ └── Upload.cshtml ├── Shared │ ├── Error.cshtml │ ├── _Layout.cshtml │ └── _ValidationScriptsPartial.cshtml ├── _ViewImports.cshtml └── _ViewStart.cshtml ├── app.config ├── appsettings.Development.json ├── appsettings.json ├── bower.json ├── bundleconfig.json ├── web.config └── wwwroot ├── css ├── site.css └── site.min.css ├── favicon.ico ├── images ├── banner1.svg ├── banner2.svg ├── banner3.svg └── banner4.svg ├── js ├── site.js └── site.min.js └── lib ├── bootstrap ├── .bower.json ├── LICENSE └── dist │ ├── css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap-theme.min.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ └── bootstrap.min.css.map │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 │ └── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ └── npm.js ├── jquery-validation-unobtrusive ├── .bower.json ├── jquery.validate.unobtrusive.js └── jquery.validate.unobtrusive.min.js ├── jquery-validation ├── .bower.json ├── LICENSE.md └── dist │ ├── additional-methods.js │ ├── additional-methods.min.js │ ├── jquery.validate.js │ └── jquery.validate.min.js └── jquery ├── .bower.json ├── LICENSE.txt └── dist ├── jquery.js ├── jquery.min.js └── jquery.min.map /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /AutomaticScalingPattern/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AutomaticScalingPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.Management.AppService.Fluent; 2 | using Microsoft.Azure.Management.Fluent; 3 | using Microsoft.Azure.Management.ResourceManager.Fluent; 4 | using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication; 5 | using System; 6 | using System.Linq; 7 | 8 | namespace AutomaticScalingPattern 9 | { 10 | class Program 11 | { 12 | static void Main(string[] args) 13 | { 14 | IAzure azure = Authenticate(); 15 | 16 | //get the first plan in the list (I assume that there is one plan) 17 | var plan = azure.AppServices.AppServicePlans.List().First(); 18 | 19 | //scale back to "Basic" on the weekend 20 | if (plan.PricingTier.SkuDescription.Tier != "Basic" && 21 | (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || 22 | DateTime.Now.DayOfWeek == DayOfWeek.Sunday)) 23 | { 24 | plan.Update() 25 | .WithPricingTier(new PricingTier("Basic", "B1")) 26 | .Apply(); 27 | } 28 | //otherwise scale up to Standard 29 | else if (plan.PricingTier.SkuDescription.Tier != "Standard") 30 | { 31 | plan.Update() 32 | .WithPricingTier(new PricingTier("Standard", "S1")) 33 | .Apply(); 34 | } 35 | 36 | plan.Update() 37 | .WithCapacity(plan.Capacity * 2) 38 | .Apply(); 39 | } 40 | 41 | private static IAzure Authenticate() 42 | { 43 | //https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal 44 | 45 | var servicePrincipal = new ServicePrincipalLoginInformation(); 46 | servicePrincipal.ClientId = "c60c8d66-caab-4359-9e1d-27e3b73fa42c"; 47 | servicePrincipal.ClientSecret = "dBB45loRs1uc0yZjiXfIrMXPm3CvL5tOEMWv10MH5Hc="; 48 | 49 | AzureCredentials credentials = 50 | new AzureCredentials(servicePrincipal, "f988fbf0-6866-43df-8926-e451715257e8" 51 | , AzureEnvironment.AzureGlobalCloud); 52 | 53 | IAzure azure = Azure.Authenticate(credentials).WithDefaultSubscription(); 54 | return azure; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /AutomaticScalingPattern/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AutomaticScalingPattern")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("AutomaticScalingPattern")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fb56ef64-1b62-4bcd-8b0a-d95eab5e2071")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /AutomaticScalingPattern/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CQRSPattern/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CQRSPattern/CQRSPattern.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {AA245C02-B056-482C-A636-9C049F8FB550} 8 | Exe 9 | CQRSPattern 10 | CQRSPattern 11 | v4.5.2 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /CQRSPattern/DataStores/CommandDataStore.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CQRSPattern 4 | { 5 | public static class CommandDataStore 6 | { 7 | static CommandDataStore() 8 | { 9 | CarDetails = new List(); 10 | } 11 | public static List CarDetails { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /CQRSPattern/DataStores/QueryDataStore.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace CQRSPattern 4 | { 5 | public static class QueryDataStore 6 | { 7 | static QueryDataStore() 8 | { 9 | Cars = new List(); 10 | } 11 | 12 | public static List Cars { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /CQRSPattern/Models/Car.cs: -------------------------------------------------------------------------------- 1 | namespace CQRSPattern 2 | { 3 | public class Car 4 | { 5 | public int Id { get; set; } 6 | 7 | public string BrandName { get; set; } 8 | 9 | public int Year { get; set; } 10 | 11 | public double Price { get; set; } 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /CQRSPattern/Models/CarDetails.cs: -------------------------------------------------------------------------------- 1 | namespace CQRSPattern 2 | { 3 | public class CarDetails 4 | { 5 | public int Id { get; set; } 6 | 7 | public string BrandName { get; set; } 8 | 9 | public string LicenseNumber { get; set; } 10 | 11 | public bool Insured{ get; set; } 12 | 13 | public double Emissions { get; set; } 14 | 15 | public int Year { get; set; } 16 | 17 | public double Price { get; set; } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CQRSPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace CQRSPattern 5 | { 6 | class Program 7 | { 8 | private static CarCommandService _commandService 9 | = new CarCommandService(); 10 | private static CarQueryService _queryService 11 | = new CarQueryService(); 12 | 13 | static void Main(string[] args) 14 | { 15 | Console.WriteLine("Press Key to create a car..."); 16 | Console.ReadLine(); 17 | 18 | _commandService.CreateCar(new CarDetails 19 | { 20 | Id = 6546, 21 | BrandName = "Toyota", 22 | Emissions = 0.9, 23 | Insured = true, 24 | LicenseNumber = "ZZ-KK89-LLP", 25 | Price = 35000, 26 | Year = 2012 27 | }); 28 | 29 | _commandService.CreateCar(new CarDetails 30 | { 31 | Id = 123587, 32 | BrandName = "Ford", 33 | Emissions = 1.5, 34 | Insured = true, 35 | LicenseNumber = "OO-MYFORD-07", 36 | Price = 12500, 37 | Year = 2007 38 | }); 39 | 40 | Console.WriteLine("Press Key to read the first car info..."); 41 | Console.ReadLine(); 42 | 43 | Car car = _queryService.GetCar(6546); 44 | 45 | Console.WriteLine("Brand: " + car.BrandName); 46 | Console.WriteLine("Year: " + car.Year); 47 | Console.WriteLine("Price: " + car.Price); 48 | 49 | Console.WriteLine("Press Key to update car year..."); 50 | Console.ReadLine(); 51 | 52 | _commandService.ChangeCarYear(car.Id, 2007); 53 | 54 | Console.WriteLine("Press Key to get cars from 2007..."); 55 | Console.ReadLine(); 56 | 57 | List cars = _queryService.GetCarsFromYear(2007); 58 | foreach (var c in cars) 59 | { 60 | Console.WriteLine("2007 car brand: " + c.BrandName); 61 | } 62 | 63 | Console.ReadLine(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /CQRSPattern/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CQRSPattern")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CQRSPattern")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("aa245c02-b056-482c-a636-9c049f8fb550")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CQRSPattern/Services/CarCommandService.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace CQRSPattern 4 | { 5 | public class CarCommandService 6 | { 7 | public void CreateCar(CarDetails car) 8 | { 9 | CommandDataStore.CarDetails.Add(car); 10 | 11 | //update the read datastore 12 | ConsitencyWorker.Create(car); 13 | } 14 | 15 | public void ChangeCarYear(int id, int year) 16 | { 17 | CarDetails car = 18 | CommandDataStore.CarDetails.Single(c => c.Id == id); 19 | if(car != null) 20 | { 21 | car.Year = year; 22 | } 23 | 24 | //update the read datastore 25 | ConsitencyWorker.UpdateYear(id, year); 26 | } 27 | 28 | public void DeleteCar(int id) 29 | { 30 | CommandDataStore.CarDetails 31 | .Remove(CommandDataStore.CarDetails.Single(c => c.Id == id)); 32 | 33 | //update the read datastore 34 | ConsitencyWorker.Delete(id); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /CQRSPattern/Services/CarQueryService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace CQRSPattern 5 | { 6 | public class CarQueryService 7 | { 8 | public Car GetCar(int id) 9 | { 10 | return QueryDataStore.Cars.Single(c => c.Id == id); 11 | } 12 | 13 | public List GetCarsFromYear(int year) 14 | { 15 | return QueryDataStore.Cars.Where(c => c.Year == year).ToList(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CQRSPattern/Services/ConsitencyWorker.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace CQRSPattern 4 | { 5 | public static class ConsitencyWorker 6 | { 7 | public static void Create(CarDetails car) 8 | { 9 | QueryDataStore.Cars.Add( 10 | new Car 11 | { 12 | Id = car.Id, 13 | BrandName = car.BrandName, 14 | Price = car.Price, 15 | Year = car.Year 16 | } 17 | ); 18 | } 19 | 20 | public static void UpdateYear(int id, int year) 21 | { 22 | Car car = QueryDataStore.Cars.Single(c => c.Id == id); 23 | if (car != null) 24 | { 25 | car.Year = year; 26 | } 27 | } 28 | 29 | public static void Delete(int id) 30 | { 31 | QueryDataStore.Cars 32 | .Remove(QueryDataStore.Cars.Single(c => c.Id == id)); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CacheAsidePattern/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CacheAsidePattern/CacheAsidePattern.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5332648B-DC4A-4743-87A1-098F54AA94E1} 8 | Exe 9 | CacheAsidePattern 10 | CacheAsidePattern 11 | v4.5.2 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\packages\StackExchange.Redis.1.2.3\lib\net45\StackExchange.Redis.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /CacheAsidePattern/CacheService.cs: -------------------------------------------------------------------------------- 1 | using StackExchange.Redis; 2 | using System; 3 | using System.Configuration; 4 | 5 | namespace CacheAsidePattern 6 | { 7 | public static class CacheService 8 | { 9 | 10 | private static Lazy lazyConnection = new Lazy(() => 11 | { 12 | var connectionString = 13 | ConfigurationManager.ConnectionStrings["AzureRedisConnectionString"].ConnectionString; 14 | 15 | return ConnectionMultiplexer.Connect(connectionString); 16 | }); 17 | 18 | public static ConnectionMultiplexer Connection 19 | { 20 | get 21 | { 22 | return lazyConnection.Value; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CacheAsidePattern/FakeDataSource.cs: -------------------------------------------------------------------------------- 1 | namespace CacheAsidePattern 2 | { 3 | public static class FakeDataSource 4 | { 5 | private static string value = "The value to return"; 6 | 7 | public static string GetValueFromDataSource(string key) 8 | { 9 | return value; 10 | } 11 | 12 | public static void UpdateValueToDataSource(string key, string newValue) 13 | { 14 | value = newValue; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CacheAsidePattern/Program.cs: -------------------------------------------------------------------------------- 1 | using StackExchange.Redis; 2 | 3 | namespace CacheAsidePattern 4 | { 5 | class Program 6 | { 7 | 8 | static void Main(string[] args) 9 | { 10 | string key = "examplekey"; 11 | 12 | //clear the cache to prep for first use 13 | ClearCache(key); 14 | 15 | //get value twice to demonstarte pattern 16 | string value = GetValue(key); 17 | value = GetValue(key); 18 | 19 | value = "I've just update this value"; 20 | 21 | //update and invalidate 22 | UpdateValue(key, value); 23 | 24 | //get value twice to demonstarte pattern 25 | string newValue = GetValue(key); 26 | newValue = GetValue(key); 27 | 28 | } 29 | 30 | public static string GetValue(string key) 31 | { 32 | string value = string.Empty; 33 | 34 | //get the value from the cache 35 | IDatabase cache = CacheService.Connection.GetDatabase(); 36 | RedisValue valueInCache = cache.StringGet(key); 37 | 38 | if (valueInCache.HasValue) //value is in the cache 39 | { 40 | value = valueInCache.ToString(); 41 | } 42 | else //value is not in the cache 43 | { 44 | //get value from datasource 45 | value = FakeDataSource.GetValueFromDataSource(key); 46 | 47 | //set value in cache 48 | cache.StringSet(key, value); 49 | } 50 | 51 | return value; 52 | } 53 | 54 | public static void UpdateValue(string key, string value) 55 | { 56 | //invalidate the cache value for the key 57 | IDatabase cache = CacheService.Connection.GetDatabase(); 58 | cache.KeyDelete(key); 59 | 60 | //update the value in the datasource 61 | FakeDataSource.UpdateValueToDataSource(key, value); 62 | } 63 | 64 | public static void ClearCache(string key) 65 | { 66 | IDatabase cache = CacheService.Connection.GetDatabase(); 67 | cache.KeyDelete(key); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /CacheAsidePattern/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CacheAsidePattern")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CacheAsidePattern")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5332648b-dc4a-4743-87a1-098f54aa94e1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CacheAsidePattern/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /CircuitBreakerPattern/CircuitBreaker/CircuitBreaker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CircuitBreakerPattern 4 | { 5 | public class CircuitBreaker 6 | { 7 | private readonly ICircuitBreakerStateStore stateStore 8 | = new CircuitBreakerStateStore(); 9 | 10 | //The time that the breaker should remain open, 11 | //before testing it in the halfopen state 12 | private TimeSpan OpenTimeOutTime = new TimeSpan(0, 0, 10); 13 | 14 | public void ExecuteAction(Action action) 15 | { 16 | if (!stateStore.IsClosed) 17 | { 18 | //The circuit breaker is open. Test if the timeout is elapsed 19 | //This is a very simple check. You could do more complex tests to put the 20 | //circuit breaker in the halfopen state 21 | if (stateStore.LastChangedDateUtc + OpenTimeOutTime < DateTime.UtcNow) 22 | { 23 | //The timeout has expired, so allow the action to be executed 24 | //This tests if the external service is up and running again 25 | //You could do more complex tests 26 | try 27 | { 28 | stateStore.HalfOpen(); 29 | 30 | //Try the call 31 | action(); 32 | 33 | //If the call succeeded, we assume that the external service 34 | //is up and running so we rest the circuit breaker to the closed state 35 | stateStore.Reset(); 36 | return; 37 | } 38 | catch (Exception ex) 39 | { 40 | //The call didn't succeed, so the service is not working yet 41 | //Thereofre, trip the circuit breaker again, setting a new exception 42 | //and putting it in the open state 43 | stateStore.Trip(ex); 44 | 45 | throw; 46 | } 47 | } 48 | 49 | //The timout hasn't elapsed yet, so the call is not made. 50 | //Let the caller know by returning a CircuitBreakerOpenException 51 | throw new CircuitBreakerOpenException(stateStore.LastException); 52 | } 53 | 54 | //The circuit breaker is closed, call the external service 55 | try 56 | { 57 | action(); 58 | } 59 | catch (Exception ex) 60 | { 61 | //The call didn't succeed, trip the circuit breaker 62 | TrackException(ex); 63 | 64 | //Throw the exception so that the caller can tell 65 | //the type of exception that was thrown. 66 | throw; 67 | } 68 | } 69 | 70 | private void TrackException(Exception ex) 71 | { 72 | //This is a very simple example. The circuit breaker trips on the first exception, 73 | //without any additional checks. You can make this more robust by tripping the 74 | //circuit breaker after a set number of failures or after another test 75 | stateStore.Trip(ex); 76 | } 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /CircuitBreakerPattern/CircuitBreaker/CircuitBreakerOpenException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace CircuitBreakerPattern 5 | { 6 | [Serializable] 7 | internal class CircuitBreakerOpenException : Exception 8 | { 9 | 10 | 11 | public CircuitBreakerOpenException() 12 | { 13 | } 14 | 15 | public CircuitBreakerOpenException(Exception lastException) 16 | : base("Method not called", lastException) 17 | { 18 | 19 | } 20 | 21 | public CircuitBreakerOpenException(string message) 22 | : base(message) 23 | { 24 | } 25 | 26 | public CircuitBreakerOpenException(string message, Exception innerException) 27 | : base(message, innerException) 28 | { 29 | } 30 | 31 | protected CircuitBreakerOpenException(SerializationInfo info, StreamingContext context) 32 | : base(info, context) 33 | { 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /CircuitBreakerPattern/CircuitBreaker/CircuitBreakerStateEnum.cs: -------------------------------------------------------------------------------- 1 | namespace CircuitBreakerPattern 2 | { 3 | public enum CircuitBreakerStateEnum 4 | { 5 | Open, 6 | HalfOpen, 7 | Closed 8 | } 9 | } -------------------------------------------------------------------------------- /CircuitBreakerPattern/CircuitBreaker/CircuitBreakerStateStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CircuitBreakerPattern 4 | { 5 | /// 6 | /// This class acts as an in-memory store for the state and additional 7 | /// information for the circuit breaker 8 | /// 9 | public class CircuitBreakerStateStore : ICircuitBreakerStateStore 10 | { 11 | public CircuitBreakerStateStore() 12 | { 13 | //set the default state of the circuit breaker state store 14 | State = CircuitBreakerStateEnum.Closed; 15 | } 16 | 17 | public CircuitBreakerStateEnum State { get; set; } 18 | 19 | public Exception LastException { get; set; } 20 | 21 | public DateTime LastChangedDateUtc { get; set; } 22 | 23 | public bool IsClosed 24 | { 25 | get 26 | { 27 | //the circuit breaker is closed when it is not Open or HalfOpen 28 | return (State == CircuitBreakerStateEnum.Closed); 29 | } 30 | set { } 31 | } 32 | 33 | 34 | public void HalfOpen() 35 | { 36 | State = CircuitBreakerStateEnum.HalfOpen; 37 | } 38 | 39 | public void Reset() 40 | { 41 | State = CircuitBreakerStateEnum.Closed; 42 | } 43 | 44 | public void Trip(Exception ex) 45 | { 46 | //set to open and add additional info 47 | State = CircuitBreakerStateEnum.Open; 48 | LastException = ex; 49 | LastChangedDateUtc = DateTime.UtcNow; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /CircuitBreakerPattern/CircuitBreaker/ICircuitBreakerStateStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CircuitBreakerPattern 4 | { 5 | interface ICircuitBreakerStateStore 6 | { 7 | CircuitBreakerStateEnum State { get; } 8 | 9 | Exception LastException { get; } 10 | 11 | DateTime LastChangedDateUtc { get; } 12 | 13 | void Trip(Exception ex); 14 | 15 | void Reset(); 16 | 17 | void HalfOpen(); 18 | 19 | bool IsClosed { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CircuitBreakerPattern/CircuitBreakerPattern.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5228B143-77B1-40D8-9988-38CD1816829C} 8 | Exe 9 | CircuitBreakerPattern 10 | CircuitBreakerPattern 11 | v4.5.2 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /CircuitBreakerPattern/ExternalService/ExternalService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CircuitBreakerPattern 4 | { 5 | public class ExternalService 6 | { 7 | //Create a static random to improve the chance to get random numbers 8 | private static Random random = new Random(); 9 | private static int failureCount = 0; 10 | 11 | public int CallMe() 12 | { 13 | //Get a random number and try to devide it by 2. 14 | //If it is divisible by 2 and failurecount < 5, call failed 15 | int testNumber = random.Next(); 16 | if (testNumber % 2 == 0 && failureCount < 5) 17 | { 18 | failureCount++; 19 | throw new Exception("I failed! Non-Transient Error " + testNumber); 20 | } 21 | 22 | failureCount = 0; 23 | return testNumber; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CircuitBreakerPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace CircuitBreakerPattern 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | var breaker = new CircuitBreaker(); 10 | var service = new ExternalService(); 11 | 12 | do 13 | { 14 | try 15 | { 16 | breaker.ExecuteAction(() => 17 | { 18 | // Call protected by the circuit breaker. 19 | int result = service.CallMe(); 20 | 21 | //log the results 22 | Console.WriteLine(DateTime.UtcNow.ToLongTimeString() 23 | + " CallMe succeeded " + result); 24 | }); 25 | } 26 | catch (CircuitBreakerOpenException ex) 27 | { 28 | // The circuit breaker is open, so the call wasn't made 29 | Console.WriteLine(DateTime.UtcNow.ToLongTimeString() 30 | + " CallMe not called " + ex.InnerException.Message); 31 | } 32 | catch (Exception ex) 33 | { 34 | //The call was made and failed 35 | Console.WriteLine(DateTime.UtcNow.ToLongTimeString() 36 | + " CallMe failed " + ex.Message); 37 | } 38 | 39 | Console.ReadLine(); 40 | 41 | } while (true); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /CircuitBreakerPattern/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CircuitBreakerPattern")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CircuitBreakerPattern")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5228b143-77b1-40d8-9988-38cd1816829c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /EventSourcingPattern/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /EventSourcingPattern/Commands/CashDepositCommand.cs: -------------------------------------------------------------------------------- 1 | namespace EventSourcingPattern 2 | { 3 | public class CashDepositCommand : Command 4 | { 5 | public double Amount { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /EventSourcingPattern/Commands/CashWithdrawalCommand.cs: -------------------------------------------------------------------------------- 1 | namespace EventSourcingPattern 2 | { 3 | public class CashWithdrawalCommand : Command 4 | { 5 | public double Amount { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /EventSourcingPattern/EventSourcingPattern.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E28F9996-4898-4716-8986-52825781D8CD} 8 | Exe 9 | EventSourcingPattern 10 | EventSourcingPattern 11 | v4.5.2 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\packages\NEventStore.5.2.0\lib\net40\NEventStore.dll 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Always 58 | Designer 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /EventSourcingPattern/EventStore/Command.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EventSourcingPattern 4 | { 5 | public class Command 6 | { 7 | public Guid EventId { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /EventSourcingPattern/EventStore/EventStore.cs: -------------------------------------------------------------------------------- 1 | using NEventStore; 2 | using NEventStore.Persistence.Sql.SqlDialects; 3 | using System; 4 | 5 | namespace EventSourcingPattern 6 | { 7 | /// 8 | /// I'm using NEventStore 9 | /// https://github.com/NEventStore/NEventStore 10 | /// 11 | public class EventStore : IDisposable 12 | { 13 | private IStoreEvents _store; 14 | 15 | public EventStore() 16 | { 17 | _store = Wireup.Init() 18 | //uncomment these lines to enable SQL Server as a datastore 19 | //Also, put your SQL Server connectionstring in App.config 20 | 21 | //.UsingSqlPersistence("SqlConnectionString") 22 | //.WithDialect(new MsSqlDialect()) 23 | 24 | //comment when using another datastore 25 | .UsingInMemoryPersistence() 26 | .InitializeStorageEngine() 27 | .UsingJsonSerialization() 28 | .Build(); 29 | } 30 | 31 | /// 32 | /// Write a new event to the event store 33 | /// 34 | /// 35 | /// 36 | public void AppendToStream(Guid streamId, Command command) 37 | { 38 | using (IEventStream stream = _store.OpenStream(streamId, 0, int.MaxValue)) 39 | { 40 | stream.Add(new EventMessage { Body = command }); 41 | stream.CommitChanges(command.EventId); 42 | } 43 | } 44 | 45 | 46 | /// 47 | /// Replay the events in the event store (by the current stream Id) 48 | /// and count and retun the amount 49 | /// 50 | /// 51 | /// 52 | public double GetAmount(Guid streamId) 53 | { 54 | double result = 0; 55 | 56 | using (var stream = _store.OpenStream(streamId, 0, int.MaxValue)) 57 | { 58 | //read the event as a dynamic type so that we don't have to explicitely 59 | //cast to CashDepositCommand or CashWithdrawalCommand 60 | foreach (dynamic item in stream.CommittedEvents) 61 | { 62 | result+= item.Body.Amount; 63 | } 64 | } 65 | 66 | return result; 67 | } 68 | 69 | public void Dispose() 70 | { 71 | _store.Dispose(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /EventSourcingPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EventSourcingPattern 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | using (EventStore store = new EventStore()) 10 | { 11 | //create a new streamID. This wil be used for partitioning 12 | Guid streamId = Guid.NewGuid(); 13 | 14 | //create things that happened 15 | var depositevent1 = new CashDepositCommand { Amount = 100, EventId = Guid.NewGuid() }; 16 | var depositevent2 = new CashDepositCommand { Amount = 20, EventId = Guid.NewGuid() }; 17 | var withdrawalevent1 = new CashWithdrawalCommand { Amount = -75, EventId = Guid.NewGuid() }; 18 | //100 + 20 - 75 = 45 19 | 20 | //commit those things 21 | store.AppendToStream(streamId, depositevent1); 22 | store.AppendToStream(streamId, depositevent2); 23 | store.AppendToStream(streamId, withdrawalevent1); 24 | 25 | //replay the events and get the current state of the data 26 | double stateOfData = store.GetAmount(streamId); 27 | 28 | Console.WriteLine("Balance: " + stateOfData); 29 | Console.ReadLine(); 30 | } 31 | 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /EventSourcingPattern/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EventSourcingPattern")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("EventSourcingPattern")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e28f9996-4898-4716-8986-52825781d8cd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /EventSourcingPattern/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternApplication/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternApplication/Program.cs: -------------------------------------------------------------------------------- 1 | using QueueBasedLoadLevelingPatternLibary; 2 | using System; 3 | using System.Threading; 4 | 5 | namespace QueueBasedLoadLevelingPatternApplication 6 | { 7 | class Program 8 | { 9 | private static Random _random = new Random(); 10 | private static QueueService _queueService = new QueueService(); 11 | 12 | static void Main(string[] args) 13 | { 14 | Console.WriteLine("Press key to start..."); 15 | Console.ReadLine(); 16 | 17 | do 18 | { 19 | var message = "new message " + _random.Next(); 20 | _queueService.QueueNewMessage(message); 21 | 22 | Console.WriteLine(DateTime.Now.ToLongTimeString() + " " + message); 23 | 24 | Thread.Sleep(2000); 25 | 26 | } while (true); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternApplication/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("QueueBasedLoadLevelingPatternApplication")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("QueueBasedLoadLevelingPatternApplication")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("372cf8a3-506d-4f94-91f6-0a0519fc1cd9")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternApplication/QueueBasedLoadLevelingPatternApplication.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {372CF8A3-506D-4F94-91F6-0A0519FC1CD9} 8 | Exe 9 | QueueBasedLoadLevelingPatternApplication 10 | QueueBasedLoadLevelingPatternApplication 11 | v4.5.2 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {d580da45-628d-4381-afa0-62f6855ee52a} 54 | QueueBasedLoadLevelingPatternLibary 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternLibary/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("QueueBasedLoadLevelingPatternLibary")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("QueueBasedLoadLevelingPatternLibary")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d580da45-628d-4381-afa0-62f6855ee52a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternLibary/QueueBasedLoadLevelingPatternLibary.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D580DA45-628D-4381-AFA0-62F6855EE52A} 8 | Library 9 | Properties 10 | QueueBasedLoadLevelingPatternLibary 11 | QueueBasedLoadLevelingPatternLibary 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll 35 | 36 | 37 | ..\packages\Microsoft.Data.Edm.5.8.2\lib\net40\Microsoft.Data.Edm.dll 38 | 39 | 40 | ..\packages\Microsoft.Data.OData.5.8.2\lib\net40\Microsoft.Data.OData.dll 41 | 42 | 43 | ..\packages\Microsoft.Data.Services.Client.5.8.2\lib\net40\Microsoft.Data.Services.Client.dll 44 | 45 | 46 | ..\packages\WindowsAzure.Storage.8.1.1\lib\net45\Microsoft.WindowsAzure.Storage.dll 47 | 48 | 49 | ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll 50 | True 51 | 52 | 53 | 54 | 55 | 56 | ..\packages\System.Spatial.5.8.2\lib\net40\System.Spatial.dll 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternLibary/QueueService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.WindowsAzure.Storage; 2 | using Microsoft.WindowsAzure.Storage.Queue; 3 | using Microsoft.WindowsAzure.Storage.RetryPolicies; 4 | using System.Configuration; 5 | 6 | namespace QueueBasedLoadLevelingPatternLibary 7 | { 8 | public class QueueService { 9 | 10 | private CloudStorageAccount _storageAccount; 11 | 12 | public QueueService() 13 | { 14 | //get the azure storage connectionstring from config. If it doesnt exist, this will throw an exception 15 | var connectionString = 16 | ConfigurationManager.ConnectionStrings["AzureStorageConnectionString"].ConnectionString; 17 | 18 | _storageAccount = CloudStorageAccount.Parse(connectionString); 19 | 20 | } 21 | 22 | public void QueueNewMessage(string newMessage) 23 | { 24 | // Create the CloudQueueClient object for the storage account. 25 | CloudQueueClient queueClient = _storageAccount.CreateCloudQueueClient(); 26 | 27 | // Get a reference to the CloudQueue named "NewQueue" 28 | CloudQueue newQueue = queueClient.GetQueueReference("newqueue"); 29 | 30 | // Create the CloudQueue if it does not exist. 31 | newQueue.CreateIfNotExists(); 32 | 33 | // Create a message and add it to the queue. 34 | CloudQueueMessage message = new CloudQueueMessage(newMessage); 35 | newQueue.AddMessage(message); 36 | } 37 | 38 | 39 | 40 | public CloudQueueMessage PeekAtMessage() 41 | { 42 | // Create the CloudQueueClient object for the storage account. 43 | CloudQueueClient queueClient = _storageAccount.CreateCloudQueueClient(); 44 | 45 | // Get a reference to the CloudQueue named "NewQueue" 46 | CloudQueue storeQueue = queueClient.GetQueueReference("newqueue"); 47 | 48 | //Peek at the next message in the queue 49 | //Peeking does not hide the message 50 | return storeQueue.PeekMessage(); 51 | } 52 | 53 | public CloudQueueMessage GetMessage() 54 | { 55 | // Create the CloudQueueClient object for the storage account. 56 | CloudQueueClient queueClient = _storageAccount.CreateCloudQueueClient(); 57 | 58 | // Get a reference to the CloudQueue named "NewQueue" 59 | CloudQueue storeQueue = queueClient.GetQueueReference("newqueue"); 60 | 61 | //Gets the next message in the queue and sets it invisble 62 | //By default, it is invisible for other callers for 30 seconds 63 | return storeQueue.GetMessage(); 64 | } 65 | 66 | public void DeleteMessage(CloudQueueMessage message) 67 | { 68 | // Create the CloudQueueClient object for the storage account. 69 | CloudQueueClient queueClient = _storageAccount.CreateCloudQueueClient(); 70 | 71 | // Get a reference to the CloudQueue named "NewQueue" 72 | CloudQueue storeQueue = queueClient.GetQueueReference("newqueue"); 73 | 74 | //Deletes the message from the queue 75 | storeQueue.DeleteMessage(message); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternLibary/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternService/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternService/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.WindowsAzure.Storage.Queue; 2 | using QueueBasedLoadLevelingPatternLibary; 3 | using System; 4 | using System.Threading; 5 | 6 | namespace QueueBasedLoadLevelingPatternService 7 | { 8 | class Program 9 | { 10 | 11 | private static QueueService _queueService = new QueueService(); 12 | 13 | static void Main(string[] args) 14 | { 15 | Console.WriteLine("Press key to start..."); 16 | Console.ReadLine(); 17 | 18 | do 19 | { 20 | CloudQueueMessage peekedMessage = _queueService.PeekAtMessage(); 21 | 22 | if (peekedMessage == null) 23 | { 24 | break; 25 | 26 | 27 | 28 | } 29 | 30 | Console.WriteLine(DateTime.Now.ToLongTimeString() + " Peeked at: " + peekedMessage.AsString); 31 | 32 | CloudQueueMessage message = _queueService.GetMessage(); 33 | 34 | Console.WriteLine(DateTime.Now.ToLongTimeString() + " Got message: " + message.AsString); 35 | Console.WriteLine(DateTime.Now.ToLongTimeString() + " Processing message.."); 36 | _queueService.DeleteMessage(message); 37 | 38 | Thread.Sleep(1000); 39 | 40 | } while (true); 41 | 42 | Console.WriteLine(DateTime.Now.ToLongTimeString() + " No messages in the queue!"); 43 | Console.ReadLine(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternService/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("QueueBasedLoadLevelingPatternService")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("QueueBasedLoadLevelingPatternService")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ff4cb589-c2a4-4481-9de3-0eea0a308c73")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternService/QueueBasedLoadLevelingPatternService.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FF4CB589-C2A4-4481-9DE3-0EEA0A308C73} 8 | Exe 9 | QueueBasedLoadLevelingPatternService 10 | QueueBasedLoadLevelingPatternService 11 | v4.5.2 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll 37 | 38 | 39 | ..\packages\Microsoft.Data.Edm.5.8.2\lib\net40\Microsoft.Data.Edm.dll 40 | 41 | 42 | ..\packages\Microsoft.Data.OData.5.8.2\lib\net40\Microsoft.Data.OData.dll 43 | 44 | 45 | ..\packages\Microsoft.Data.Services.Client.5.8.2\lib\net40\Microsoft.Data.Services.Client.dll 46 | 47 | 48 | ..\packages\WindowsAzure.Storage.8.1.1\lib\net45\Microsoft.WindowsAzure.Storage.dll 49 | 50 | 51 | ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll 52 | True 53 | 54 | 55 | 56 | 57 | ..\packages\System.Spatial.5.8.2\lib\net40\System.Spatial.dll 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | {d580da45-628d-4381-afa0-62f6855ee52a} 77 | QueueBasedLoadLevelingPatternLibary 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternService/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternWebJob/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternWebJob/Functions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.WebJobs; 2 | using System; 3 | using System.IO; 4 | 5 | namespace QueueBasedLoadLevelingPatternWebJob 6 | { 7 | public class Functions 8 | { 9 | // This function will get triggered/executed when a new message is written 10 | // on an Azure Queue called queue. 11 | public static void ProcessQueueMessage([QueueTrigger("newqueue")] string message, TextWriter log) 12 | { 13 | Console.WriteLine(DateTime.Now.ToLongTimeString() + " Processing " + message); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternWebJob/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Azure.WebJobs; 2 | 3 | namespace QueueBasedLoadLevelingPatternWebJob 4 | { 5 | // To learn more about Microsoft Azure WebJobs SDK, please see https://go.microsoft.com/fwlink/?LinkID=320976 6 | class Program 7 | { 8 | // Please set the following connection strings in app.config for this WebJob to run: 9 | // AzureWebJobsDashboard and AzureWebJobsStorage 10 | static void Main() 11 | { 12 | var config = new JobHostConfiguration(); 13 | 14 | if (config.IsDevelopment) 15 | { 16 | config.UseDevelopmentSettings(); 17 | } 18 | 19 | var host = new JobHost(); 20 | // The following code ensures that the WebJob will be running continuously 21 | host.RunAndBlock(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternWebJob/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("QueueBasedLoadLevelingPatternWebJob")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("QueueBasedLoadLevelingPatternWebJob")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("82807f44-aa56-4e94-9fb8-9696f2cdcf05")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternWebJob/QueueBasedLoadLevelingPatternWebJob.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {82807F44-AA56-4E94-9FB8-9696F2CDCF05} 8 | Exe 9 | Properties 10 | QueueBasedLoadLevelingPatternWebJob 11 | QueueBasedLoadLevelingPatternWebJob 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | true 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ..\packages\System.Spatial.5.7.0\lib\net40\System.Spatial.dll 46 | 47 | 48 | ..\packages\Microsoft.Azure.WebJobs.Core.1.1.2\lib\net45\Microsoft.Azure.WebJobs.dll 49 | 50 | 51 | ..\packages\Microsoft.Azure.WebJobs.1.1.2\lib\net45\Microsoft.Azure.WebJobs.Host.dll 52 | 53 | 54 | ..\packages\Microsoft.Data.Edm.5.7.0\lib\net40\Microsoft.Data.Edm.dll 55 | 56 | 57 | ..\packages\Microsoft.Data.OData.5.7.0\lib\net40\Microsoft.Data.OData.dll 58 | 59 | 60 | ..\packages\Microsoft.Data.Services.Client.5.7.0\lib\net40\Microsoft.Data.Services.Client.dll 61 | 62 | 63 | False 64 | ..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.2.1\lib\net40\Microsoft.WindowsAzure.Configuration.dll 65 | 66 | 67 | False 68 | ..\packages\WindowsAzure.Storage.7.0.0\lib\net40\Microsoft.WindowsAzure.Storage.dll 69 | 70 | 71 | False 72 | ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 92 | -------------------------------------------------------------------------------- /QueueBasedLoadLevelingPatternWebJob/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /RetryPattern/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /RetryPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | 8 | namespace RetryPattern 9 | { 10 | class Program 11 | { 12 | static void Main(string[] args) 13 | { 14 | StorageService storageService = new StorageService(); 15 | 16 | do 17 | { 18 | 19 | string result = storageService.ReadWriteToStorage(); 20 | 21 | Console.WriteLine(result); 22 | 23 | Console.ReadLine(); 24 | 25 | } while (true); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /RetryPattern/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RetryPattern")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RetryPattern")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8805128f-c63a-4d23-b416-563ce5eaf4b3")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /RetryPattern/RetryPattern.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8805128F-C63A-4D23-B416-563CE5EAF4B3} 8 | Exe 9 | RetryPattern 10 | RetryPattern 11 | v4.5.2 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll 37 | 38 | 39 | ..\packages\Microsoft.Data.Edm.5.8.2\lib\net40\Microsoft.Data.Edm.dll 40 | 41 | 42 | ..\packages\Microsoft.Data.OData.5.8.2\lib\net40\Microsoft.Data.OData.dll 43 | 44 | 45 | ..\packages\Microsoft.Data.Services.Client.5.8.2\lib\net40\Microsoft.Data.Services.Client.dll 46 | 47 | 48 | ..\packages\WindowsAzure.Storage.8.1.1\lib\net45\Microsoft.WindowsAzure.Storage.dll 49 | 50 | 51 | ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll 52 | True 53 | 54 | 55 | 56 | 57 | 58 | ..\packages\System.Spatial.5.8.2\lib\net40\System.Spatial.dll 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /RetryPattern/StorageService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.WindowsAzure.Storage; 2 | using Microsoft.WindowsAzure.Storage.Blob; 3 | using Microsoft.WindowsAzure.Storage.RetryPolicies; 4 | using System; 5 | using System.Configuration; 6 | 7 | namespace RetryPattern 8 | { 9 | 10 | /// 11 | /// Retry guidance: 12 | /// https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific 13 | /// 14 | public class StorageService 15 | { 16 | private CloudStorageAccount _storageAccount; 17 | 18 | public StorageService() 19 | { 20 | 21 | //get the azure storage connectionstring from config. If it doesnt exist, this will throw an exception 22 | var connectionString = 23 | ConfigurationManager.ConnectionStrings["AzureStorageConnectionString"].ConnectionString; 24 | 25 | _storageAccount = CloudStorageAccount.Parse(connectionString); 26 | } 27 | 28 | public string ReadWriteToStorage() 29 | { 30 | CloudBlobClient blobClient = CreateBlobClient(); 31 | 32 | CloudBlobContainer newContainer = blobClient.GetContainerReference("newcontainer"); 33 | 34 | newContainer.CreateIfNotExists(); 35 | 36 | CloudBlockBlob myNewBlob = newContainer.GetBlockBlobReference("mynewblob"); 37 | 38 | if (!myNewBlob.Exists()) 39 | { 40 | myNewBlob.UploadText("This is the text that the Blob contains..."); 41 | } 42 | 43 | return myNewBlob.DownloadText(); 44 | } 45 | 46 | private CloudBlobClient CreateBlobClient() 47 | { 48 | CloudBlobClient client = _storageAccount.CreateCloudBlobClient(); 49 | client.DefaultRequestOptions = new BlobRequestOptions 50 | { 51 | RetryPolicy = new ExponentialRetry(TimeSpan.FromSeconds(3), 4), 52 | 53 | LocationMode = LocationMode.PrimaryThenSecondary, 54 | 55 | MaximumExecutionTime = TimeSpan.FromSeconds(20) 56 | }; 57 | 58 | return client; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /RetryPattern/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "wwwroot/lib" 3 | } 4 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using RuntimeReconfigurationPattern.Models; 7 | using Microsoft.Extensions.Options; 8 | 9 | namespace RuntimeReconfigurationPattern.Controllers 10 | { 11 | public class HomeController : Controller 12 | { 13 | 14 | private readonly AppSettings _settings; 15 | 16 | public HomeController(IOptionsSnapshot settings) 17 | { 18 | _settings = settings.Value; 19 | } 20 | 21 | public IActionResult Index() 22 | { 23 | return Content("" + _settings.MyImportantSetting); 24 | } 25 | 26 | public IActionResult About() 27 | { 28 | ViewData["Message"] = "Your application description page."; 29 | 30 | return View(); 31 | } 32 | 33 | public IActionResult Contact() 34 | { 35 | ViewData["Message"] = "Your contact page."; 36 | 37 | return View(); 38 | } 39 | 40 | public IActionResult Error() 41 | { 42 | return View(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Models/AppSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace RuntimeReconfigurationPattern.Models 7 | { 8 | public class AppSettings 9 | { 10 | public string MyImportantSetting { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Hosting; 7 | 8 | namespace RuntimeReconfigurationPattern 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | var host = new WebHostBuilder() 15 | .UseKestrel() 16 | .UseContentRoot(Directory.GetCurrentDirectory()) 17 | .UseIISIntegration() 18 | .UseStartup() 19 | .UseApplicationInsights() 20 | .Build(); 21 | 22 | host.Run(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Properties/PublishProfiles/configchanges - Web Deploy.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | MSDeploy 9 | /subscriptions/9e4ca2fa-5f92-4266-a494-f82c52915cee/resourceGroups/configchanges/providers/Microsoft.Web/sites/configchanges 10 | configchanges 11 | AzureWebSite 12 | Release 13 | Any CPU 14 | http://configchanges.azurewebsites.net 15 | True 16 | False 17 | 18 | 6140ec31-90af-4214-b443-faef6228296c 19 | configchanges.scm.azurewebsites.net:443 20 | configchanges 21 | 22 | True 23 | WMSVC 24 | True 25 | $configchanges 26 | <_SavePWD>True 27 | <_DestinationType>AzureWebSite 28 | 29 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:61499/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "RuntimeReconfigurationPattern": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:61500" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/RuntimeReconfigurationPattern.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net461 4 | win7-x86 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Logging; 10 | using RuntimeReconfigurationPattern.Models; 11 | 12 | namespace RuntimeReconfigurationPattern 13 | { 14 | public class Startup 15 | { 16 | public Startup(IHostingEnvironment env) 17 | { 18 | var builder = new ConfigurationBuilder() 19 | .SetBasePath(env.ContentRootPath) 20 | .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) 21 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true) 22 | .AddEnvironmentVariables(); 23 | Configuration = builder.Build(); 24 | } 25 | 26 | public IConfigurationRoot Configuration { get; } 27 | 28 | // This method gets called by the runtime. Use this method to add services to the container. 29 | public void ConfigureServices(IServiceCollection services) 30 | { 31 | services.Configure(Configuration.GetSection("AppSettings")); 32 | 33 | 34 | // Add framework services. 35 | services.AddMvc(); 36 | } 37 | 38 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 39 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 40 | { 41 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 42 | loggerFactory.AddDebug(); 43 | 44 | if (env.IsDevelopment()) 45 | { 46 | app.UseDeveloperExceptionPage(); 47 | app.UseBrowserLink(); 48 | } 49 | else 50 | { 51 | app.UseExceptionHandler("/Home/Error"); 52 | } 53 | 54 | app.UseStaticFiles(); 55 | 56 | app.UseMvc(routes => 57 | { 58 | routes.MapRoute( 59 | name: "default", 60 | template: "{controller=Home}/{action=Index}/{id?}"); 61 | }); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "About"; 3 | } 4 |

@ViewData["Title"].

5 |

@ViewData["Message"]

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Contact"; 3 | } 4 |

@ViewData["Title"].

5 |

@ViewData["Message"]

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
18 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Error"; 3 | } 4 | 5 |

Error.

6 |

An error occurred while processing your request.

7 | 8 |

Development Mode

9 |

10 | Swapping to Development environment will display more detailed information about the error that occurred. 11 |

12 |

13 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 14 |

15 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet 2 | 3 | 4 | 5 | 6 | 7 | @ViewData["Title"] - RuntimeReconfigurationPattern 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | @Html.Raw(JavaScriptSnippet.FullScript) 20 | 21 | 22 | 42 |
43 | @RenderBody() 44 |
45 |
46 |

© 2017 - RuntimeReconfigurationPattern

47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 62 | 68 | 69 | 70 | 71 | @RenderSection("Scripts", required: false) 72 | 73 | 74 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using RuntimeReconfigurationPattern 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppSettings": { 3 | "MyImportantSetting": "This issss the 3rd local setting" 4 | } 5 | } -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppSettings": { 3 | "MyImportantSetting": "" 4 | } 5 | } -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asp.net", 3 | "private": true, 4 | "dependencies": { 5 | "bootstrap": "3.3.7", 6 | "jquery": "2.2.0", 7 | "jquery-validation": "1.14.0", 8 | "jquery-validation-unobtrusive": "3.2.6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/bundleconfig.json: -------------------------------------------------------------------------------- 1 | // Configure bundling and minification for the project. 2 | // More info at https://go.microsoft.com/fwlink/?LinkId=808241 3 | [ 4 | { 5 | "outputFileName": "wwwroot/css/site.min.css", 6 | // An array of relative input file paths. Globbing patterns supported 7 | "inputFiles": [ 8 | "wwwroot/css/site.css" 9 | ] 10 | }, 11 | { 12 | "outputFileName": "wwwroot/js/site.min.js", 13 | "inputFiles": [ 14 | "wwwroot/js/site.js" 15 | ], 16 | // Optionally specify minification options 17 | "minify": { 18 | "enabled": true, 19 | "renameLocals": true 20 | }, 21 | // Optionally generate .map file 22 | "sourceMap": false 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Wrapping element */ 7 | /* Set some basic padding to keep content from hitting the edges */ 8 | .body-content { 9 | padding-left: 15px; 10 | padding-right: 15px; 11 | } 12 | 13 | /* Set widths on the form inputs since otherwise they're 100% wide */ 14 | input, 15 | select, 16 | textarea { 17 | max-width: 280px; 18 | } 19 | 20 | /* Carousel */ 21 | .carousel-caption p { 22 | font-size: 20px; 23 | line-height: 1.4; 24 | } 25 | 26 | /* Make .svg files in the carousel display properly in older browsers */ 27 | .carousel-inner .item img[src$=".svg"] { 28 | width: 100%; 29 | } 30 | 31 | /* Hide/rearrange for smaller screens */ 32 | @media screen and (max-width: 767px) { 33 | /* Hide captions */ 34 | .carousel-caption { 35 | display: none; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}input,select,textarea{max-width:280px}.carousel-caption p{font-size:20px;line-height:1.4}.carousel-inner .item img[src$=".svg"]{width:100%}@media screen and (max-width:767px){.carousel-caption{display:none}} -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/RuntimeReconfigurationPattern/wwwroot/favicon.ico -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Write your Javascript code. 2 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/RuntimeReconfigurationPattern/wwwroot/js/site.min.js -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 3" 33 | }, 34 | "version": "3.3.7", 35 | "_release": "3.3.7", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.7", 39 | "commit": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" 40 | }, 41 | "_source": "https://github.com/twbs/bootstrap.git", 42 | "_target": "v3.3.7", 43 | "_originalSource": "bootstrap", 44 | "_direct": true 45 | } -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2016 Twitter, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /RuntimeReconfigurationPattern/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /ShardingPattern/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ShardingPattern/InitializeShard.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/ShardingPattern/InitializeShard.sql -------------------------------------------------------------------------------- /ShardingPattern/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Microsoft 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /ShardingPattern/README.txt: -------------------------------------------------------------------------------- 1 |  2 | Prerequisites: 3 | - Visual Studio 2012 or later, Professional Edition or higher 4 | - Nuget 2.7 or later 5 | - .NET Framework 4.5 or later 6 | - Microsoft Azure SQL Database 7 | 8 | Before running this project, please fill in the values in App.config. 9 | 10 | For detailed instructions and background information, please refer to Getting Started web page 11 | for Azure SQL Database Elastic Scale: http://go.microsoft.com/fwlink/?LinkID=510913 12 | 13 | -------------------------------------------------------------------------------- /ShardingPattern/Samples/CreateShardSample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement; 8 | 9 | namespace ElasticScaleStarterKit 10 | { 11 | internal class CreateShardSample 12 | { 13 | /// 14 | /// Creates a new shard (or uses an existing empty shard), adds it to the shard map, 15 | /// and assigns it the specified range if possible. 16 | /// 17 | public static void CreateShard(RangeShardMap shardMap, Range rangeForNewShard) 18 | { 19 | // Create a new shard, or get an existing empty shard (if a previous create partially succeeded). 20 | Shard shard = CreateOrGetEmptyShard(shardMap); 21 | 22 | // Create a mapping to that shard. 23 | RangeMapping mappingForNewShard = shardMap.CreateRangeMapping(rangeForNewShard, shard); 24 | ConsoleUtils.WriteInfo("Mapped range {0} to shard {1}", mappingForNewShard.Value, shard.Location.Database); 25 | } 26 | 27 | /// 28 | /// Script file that will be executed to initialize a shard. 29 | /// 30 | private const string InitializeShardScriptFile = "InitializeShard.sql"; 31 | 32 | /// 33 | /// Format to use for creating shard name. {0} is the number of shards that have already been created. 34 | /// 35 | private const string ShardNameFormat = "ElasticScaleStarterKit_Shard{0}"; 36 | 37 | /// 38 | /// Creates a new shard, or gets an existing empty shard (i.e. a shard that has no mappings). 39 | /// The reason why an empty shard might exist is that it was created and initialized but we 40 | /// failed to create a mapping to it. 41 | /// 42 | private static Shard CreateOrGetEmptyShard(RangeShardMap shardMap) 43 | { 44 | // Get an empty shard if one already exists, otherwise create a new one 45 | Shard shard = FindEmptyShard(shardMap); 46 | if (shard == null) 47 | { 48 | // No empty shard exists, so create one 49 | 50 | // Choose the shard name 51 | string databaseName = string.Format(ShardNameFormat, shardMap.GetShards().Count()); 52 | 53 | // Only create the database if it doesn't already exist. It might already exist if 54 | // we tried to create it previously but hit a transient fault. 55 | if (!SqlDatabaseUtils.DatabaseExists(Configuration.ShardMapManagerServerName, databaseName)) 56 | { 57 | SqlDatabaseUtils.CreateDatabase(Configuration.ShardMapManagerServerName, databaseName); 58 | } 59 | 60 | // Create schema and populate reference data on that database 61 | // The initialize script must be idempotent, in case it was already run on this database 62 | // and we failed to add it to the shard map previously 63 | SqlDatabaseUtils.ExecuteSqlScript( 64 | Configuration.ShardMapManagerServerName, databaseName, InitializeShardScriptFile); 65 | 66 | // Add it to the shard map 67 | ShardLocation shardLocation = new ShardLocation(Configuration.ShardMapManagerServerName, databaseName); 68 | shard = ShardManagementUtils.CreateOrGetShard(shardMap, shardLocation); 69 | } 70 | 71 | return shard; 72 | } 73 | 74 | /// 75 | /// Finds an existing empty shard, or returns null if none exist. 76 | /// 77 | private static Shard FindEmptyShard(RangeShardMap shardMap) 78 | { 79 | // Get all shards in the shard map 80 | IEnumerable allShards = shardMap.GetShards(); 81 | 82 | // Get all mappings in the shard map 83 | IEnumerable> allMappings = shardMap.GetMappings(); 84 | 85 | // Determine which shards have mappings 86 | HashSet shardsWithMappings = new HashSet(allMappings.Select(m => m.Shard)); 87 | 88 | // Get the first shard (ordered by name) that has no mappings, if it exists 89 | return allShards.OrderBy(s => s.Location.Database).FirstOrDefault(s => !shardsWithMappings.Contains(s)); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /ShardingPattern/Samples/MultiShardQuerySample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Data; 7 | using System.Data.Common; 8 | using System.Linq; 9 | using Microsoft.Azure.SqlDatabase.ElasticScale.Query; 10 | using Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement; 11 | 12 | namespace ElasticScaleStarterKit 13 | { 14 | internal static class MultiShardQuerySample 15 | { 16 | public static void ExecuteMultiShardQuery(RangeShardMap shardMap, string credentialsConnectionString) 17 | { 18 | // Get the shards to connect to 19 | IEnumerable shards = shardMap.GetShards(); 20 | 21 | // Create the multi-shard connection 22 | using (MultiShardConnection conn = new MultiShardConnection(shards, credentialsConnectionString)) 23 | { 24 | // Create a simple command 25 | using (MultiShardCommand cmd = conn.CreateCommand()) 26 | { 27 | // Because this query is grouped by CustomerID, which is sharded, 28 | // we will not get duplicate rows. 29 | cmd.CommandText = @" 30 | SELECT 31 | c.CustomerId, 32 | c.Name AS CustomerName, 33 | COUNT(o.OrderID) AS OrderCount 34 | FROM 35 | dbo.Customers AS c INNER JOIN 36 | dbo.Orders AS o 37 | ON c.CustomerID = o.CustomerID 38 | GROUP BY 39 | c.CustomerId, 40 | c.Name 41 | ORDER BY 42 | OrderCount"; 43 | 44 | // Append a column with the shard name where the row came from 45 | cmd.ExecutionOptions = MultiShardExecutionOptions.IncludeShardNameColumn; 46 | 47 | // Allow for partial results in case some shards do not respond in time 48 | cmd.ExecutionPolicy = MultiShardExecutionPolicy.PartialResults; 49 | 50 | // Allow the entire command to take up to 30 seconds 51 | cmd.CommandTimeout = 30; 52 | 53 | // Execute the command. 54 | // We do not need to specify retry logic because MultiShardDataReader will internally retry until the CommandTimeout expires. 55 | using (MultiShardDataReader reader = cmd.ExecuteReader()) 56 | { 57 | // Get the column names 58 | TableFormatter formatter = new TableFormatter(GetColumnNames(reader).ToArray()); 59 | 60 | int rows = 0; 61 | while (reader.Read()) 62 | { 63 | // Read the values using standard DbDataReader methods 64 | object[] values = new object[reader.FieldCount]; 65 | reader.GetValues(values); 66 | 67 | // Extract just database name from the $ShardLocation pseudocolumn to make the output formater cleaner. 68 | // Note that the $ShardLocation pseudocolumn is always the last column 69 | int shardLocationOrdinal = values.Length - 1; 70 | values[shardLocationOrdinal] = ExtractDatabaseName(values[shardLocationOrdinal].ToString()); 71 | 72 | // Add values to output formatter 73 | formatter.AddRow(values); 74 | 75 | rows++; 76 | } 77 | 78 | Console.WriteLine(formatter.ToString()); 79 | Console.WriteLine("({0} rows returned)", rows); 80 | } 81 | } 82 | } 83 | } 84 | 85 | /// 86 | /// Gets the column names from a data reader. 87 | /// 88 | private static IEnumerable GetColumnNames(DbDataReader reader) 89 | { 90 | List columnNames = new List(); 91 | foreach (DataRow r in reader.GetSchemaTable().Rows) 92 | { 93 | columnNames.Add(r[SchemaTableColumn.ColumnName].ToString()); 94 | } 95 | 96 | return columnNames; 97 | } 98 | 99 | /// 100 | /// Extracts the database name from the provided shard location string. 101 | /// 102 | private static string ExtractDatabaseName(string shardLocationString) 103 | { 104 | string[] pattern = new[] { "[", "DataSource=", "Database=", "]" }; 105 | string[] matches = shardLocationString.Split(pattern, StringSplitOptions.RemoveEmptyEntries); 106 | return matches[1]; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /ShardingPattern/ShardingPattern.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {576E2FB9-A842-457C-BA5B-5E53A2FA11A9} 9 | Exe 10 | Properties 11 | ElasticScaleStarterKit 12 | ElasticScaleStarterKit 13 | v4.5 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling 36 | 37 | 38 | Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.Data 39 | 40 | 41 | Microsoft.Azure.SqlDatabase.ElasticScale.Client 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | PreserveNewest 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /ShardingPattern/Utils/Configuration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Configuration; 5 | using System.Data.SqlClient; 6 | 7 | namespace ElasticScaleStarterKit 8 | { 9 | /// 10 | /// Provides access to app.config settings, and contains advanced configuration settings. 11 | /// 12 | internal static class Configuration 13 | { 14 | /// 15 | /// Gets the server name for the Shard Map Manager database, which contains the shard maps. 16 | /// 17 | public static string ShardMapManagerServerName 18 | { 19 | get { return ServerName; } 20 | } 21 | 22 | /// 23 | /// Gets the database name for the Shard Map Manager database, which contains the shard maps. 24 | /// 25 | public static string ShardMapManagerDatabaseName 26 | { 27 | get { return "ElasticScaleStarterKit_ShardMapManagerDb"; } 28 | } 29 | 30 | /// 31 | /// Gets the name for the Shard Map that contains metadata for all the shards and the mappings to those shards. 32 | /// 33 | public static string ShardMapName 34 | { 35 | get { return "CustomerIDShardMap"; } 36 | } 37 | 38 | /// 39 | /// Gets the server name from the App.config file for shards to be created on. 40 | /// 41 | private static string ServerName 42 | { 43 | get { return ConfigurationManager.AppSettings["ServerName"]; } 44 | } 45 | 46 | /// 47 | /// Gets the edition to use for Shards and Shard Map Manager Database if the server is an Azure SQL DB server. 48 | /// If the server is a regular SQL Server then this is ignored. 49 | /// 50 | public static string DatabaseEdition 51 | { 52 | get 53 | { 54 | return ConfigurationManager.AppSettings["DatabaseEdition"]; 55 | } 56 | } 57 | 58 | /// 59 | /// Returns a connection string that can be used to connect to the specified server and database. 60 | /// 61 | public static string GetConnectionString(string serverName, string database) 62 | { 63 | SqlConnectionStringBuilder connStr = new SqlConnectionStringBuilder(GetCredentialsConnectionString()); 64 | connStr.DataSource = serverName; 65 | connStr.InitialCatalog = database; 66 | return connStr.ToString(); 67 | } 68 | 69 | /// 70 | /// Returns a connection string to use for Data-Dependent Routing and Multi-Shard Query, 71 | /// which does not contain DataSource or InitialCatalog. 72 | /// 73 | public static string GetCredentialsConnectionString() 74 | { 75 | // Get User name and password from the app.config file. If they don't exist, default to string.Empty. 76 | string userId = ConfigurationManager.AppSettings["UserName"] ?? string.Empty; 77 | string password = ConfigurationManager.AppSettings["Password"] ?? string.Empty; 78 | 79 | // Get Integrated Security from the app.config file. 80 | // If it exists, then parse it (throw exception on failure), otherwise default to false. 81 | string integratedSecurityString = ConfigurationManager.AppSettings["IntegratedSecurity"]; 82 | bool integratedSecurity = integratedSecurityString != null && bool.Parse(integratedSecurityString); 83 | 84 | SqlConnectionStringBuilder connStr = new SqlConnectionStringBuilder 85 | { 86 | // DDR and MSQ require credentials to be set 87 | UserID = userId, 88 | Password = password, 89 | IntegratedSecurity = integratedSecurity, 90 | 91 | // DataSource and InitialCatalog cannot be set for DDR and MSQ APIs, because these APIs will 92 | // determine the DataSource and InitialCatalog for you. 93 | // 94 | // DDR also does not support the ConnectRetryCount keyword introduced in .NET 4.5.1, because it 95 | // would prevent the API from being able to correctly kill connections when mappings are switched 96 | // offline. 97 | // 98 | // Other SqlClient ConnectionString keywords are supported. 99 | 100 | ApplicationName = "ESC_SKv1.0", 101 | ConnectTimeout = 30 102 | }; 103 | return connStr.ToString(); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /ShardingPattern/Utils/ConsoleUtils.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace ElasticScaleStarterKit 7 | { 8 | internal static class ConsoleUtils 9 | { 10 | /// 11 | /// Writes detailed information to the console. 12 | /// 13 | public static void WriteInfo(string format, params object[] args) 14 | { 15 | WriteColor(ConsoleColor.DarkGray, "\t" + format, args); 16 | } 17 | 18 | /// 19 | /// Writes warning text to the console. 20 | /// 21 | public static void WriteWarning(string format, params object[] args) 22 | { 23 | WriteColor(ConsoleColor.Yellow, format, args); 24 | } 25 | 26 | /// 27 | /// Writes colored text to the console. 28 | /// 29 | public static void WriteColor(ConsoleColor color, string format, params object[] args) 30 | { 31 | ConsoleColor oldColor = Console.ForegroundColor; 32 | Console.ForegroundColor = color; 33 | Console.WriteLine(format, args); 34 | Console.ForegroundColor = oldColor; 35 | } 36 | 37 | /// 38 | /// Reads an integer from the console. 39 | /// 40 | public static int ReadIntegerInput(string prompt) 41 | { 42 | return ReadIntegerInput(prompt, allowNull: false).Value; 43 | } 44 | 45 | /// 46 | /// Reads an integer from the console, or returns null if the user enters nothing and allowNull is true. 47 | /// 48 | public static int? ReadIntegerInput(string prompt, bool allowNull) 49 | { 50 | while (true) 51 | { 52 | Console.Write(prompt); 53 | string line = Console.ReadLine(); 54 | 55 | if (string.IsNullOrWhiteSpace(line) && allowNull) 56 | { 57 | return null; 58 | } 59 | 60 | int inputValue; 61 | if (int.TryParse(line, out inputValue)) 62 | { 63 | return inputValue; 64 | } 65 | } 66 | } 67 | 68 | /// 69 | /// Reads an integer from the console. 70 | /// 71 | public static int ReadIntegerInput(string prompt, int defaultValue, Func validator) 72 | { 73 | while (true) 74 | { 75 | int? input = ReadIntegerInput(prompt, allowNull: true); 76 | 77 | if (!input.HasValue) 78 | { 79 | // No input, so return default 80 | return defaultValue; 81 | } 82 | else 83 | { 84 | // Input was provided, so validate it 85 | if (validator(input.Value)) 86 | { 87 | // Validation passed, so return 88 | return input.Value; 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ShardingPattern/Utils/ShardManagementUtils.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement; 6 | 7 | namespace ElasticScaleStarterKit 8 | { 9 | internal static class ShardManagementUtils 10 | { 11 | /// 12 | /// Tries to get the ShardMapManager that is stored in the specified database. 13 | /// 14 | public static ShardMapManager TryGetShardMapManager(string shardMapManagerServerName, string shardMapManagerDatabaseName) 15 | { 16 | string shardMapManagerConnectionString = 17 | Configuration.GetConnectionString( 18 | Configuration.ShardMapManagerServerName, 19 | Configuration.ShardMapManagerDatabaseName); 20 | 21 | if (!SqlDatabaseUtils.DatabaseExists(shardMapManagerServerName, shardMapManagerDatabaseName)) 22 | { 23 | // Shard Map Manager database has not yet been created 24 | return null; 25 | } 26 | 27 | ShardMapManager shardMapManager; 28 | bool smmExists = ShardMapManagerFactory.TryGetSqlShardMapManager( 29 | shardMapManagerConnectionString, 30 | ShardMapManagerLoadPolicy.Lazy, 31 | out shardMapManager); 32 | 33 | if (!smmExists) 34 | { 35 | // Shard Map Manager database exists, but Shard Map Manager has not been created 36 | return null; 37 | } 38 | 39 | return shardMapManager; 40 | } 41 | 42 | /// 43 | /// Creates a shard map manager in the database specified by the given connection string. 44 | /// 45 | public static ShardMapManager CreateOrGetShardMapManager(string shardMapManagerConnectionString) 46 | { 47 | // Get shard map manager database connection string 48 | // Try to get a reference to the Shard Map Manager in the Shard Map Manager database. If it doesn't already exist, then create it. 49 | ShardMapManager shardMapManager; 50 | bool shardMapManagerExists = ShardMapManagerFactory.TryGetSqlShardMapManager( 51 | shardMapManagerConnectionString, 52 | ShardMapManagerLoadPolicy.Lazy, 53 | out shardMapManager); 54 | 55 | if (shardMapManagerExists) 56 | { 57 | ConsoleUtils.WriteInfo("Shard Map Manager already exists"); 58 | } 59 | else 60 | { 61 | // The Shard Map Manager does not exist, so create it 62 | shardMapManager = ShardMapManagerFactory.CreateSqlShardMapManager(shardMapManagerConnectionString); 63 | ConsoleUtils.WriteInfo("Created Shard Map Manager"); 64 | } 65 | 66 | return shardMapManager; 67 | } 68 | 69 | /// 70 | /// Creates a new Range Shard Map with the specified name, or gets the Range Shard Map if it already exists. 71 | /// 72 | public static RangeShardMap CreateOrGetRangeShardMap(ShardMapManager shardMapManager, string shardMapName) 73 | { 74 | // Try to get a reference to the Shard Map. 75 | RangeShardMap shardMap; 76 | bool shardMapExists = shardMapManager.TryGetRangeShardMap(shardMapName, out shardMap); 77 | 78 | if (shardMapExists) 79 | { 80 | ConsoleUtils.WriteInfo("Shard Map {0} already exists", shardMap.Name); 81 | } 82 | else 83 | { 84 | // The Shard Map does not exist, so create it 85 | shardMap = shardMapManager.CreateRangeShardMap(shardMapName); 86 | ConsoleUtils.WriteInfo("Created Shard Map {0}", shardMap.Name); 87 | } 88 | 89 | return shardMap; 90 | } 91 | 92 | /// 93 | /// Adds Shards to the Shard Map, or returns them if they have already been added. 94 | /// 95 | public static Shard CreateOrGetShard(ShardMap shardMap, ShardLocation shardLocation) 96 | { 97 | // Try to get a reference to the Shard 98 | Shard shard; 99 | bool shardExists = shardMap.TryGetShard(shardLocation, out shard); 100 | 101 | if (shardExists) 102 | { 103 | ConsoleUtils.WriteInfo("Shard {0} has already been added to the Shard Map", shardLocation.Database); 104 | } 105 | else 106 | { 107 | // The Shard Map does not exist, so create it 108 | shard = shardMap.CreateShard(shardLocation); 109 | ConsoleUtils.WriteInfo("Added shard {0} to the Shard Map", shardLocation.Database); 110 | } 111 | 112 | return shard; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ShardingPattern/Utils/TableFormatter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace ElasticScaleStarterKit 10 | { 11 | /// 12 | /// Stores tabular data and formats it for writing to output. 13 | /// 14 | internal class TableFormatter 15 | { 16 | /// 17 | /// Table column names. 18 | /// 19 | private readonly string[] _columnNames; 20 | 21 | /// 22 | /// Table rows. 23 | /// 24 | private readonly List _rows; 25 | 26 | public TableFormatter(string[] columnNames) 27 | { 28 | _columnNames = columnNames; 29 | _rows = new List(); 30 | } 31 | 32 | public void AddRow(object[] values) 33 | { 34 | if (values.Length != _columnNames.Length) 35 | { 36 | throw new ArgumentException(string.Format("Incorrect number of fields. Expected {0}, actual {1}", _columnNames.Length, values.Length)); 37 | } 38 | 39 | string[] valueStrings = values.Select(o => o.ToString()).ToArray(); 40 | 41 | _rows.Add(valueStrings); 42 | } 43 | 44 | public override string ToString() 45 | { 46 | StringBuilder output = new StringBuilder(); 47 | 48 | // Determine column widths 49 | int[] columnWidths = new int[_columnNames.Length]; 50 | for (int c = 0; c < _columnNames.Length; c++) 51 | { 52 | int maxValueLength = 0; 53 | 54 | if (_rows.Any()) 55 | { 56 | maxValueLength = _rows.Select(r => r[c].Length).Max(); 57 | } 58 | 59 | columnWidths[c] = Math.Max(maxValueLength, _columnNames[c].Length); 60 | } 61 | 62 | // Build format strings that are used to format the column names and fields 63 | string[] formatStrings = new string[_columnNames.Length]; 64 | for (int c = 0; c < _columnNames.Length; c++) 65 | { 66 | formatStrings[c] = string.Format(" {{0,-{0}}} ", columnWidths[c]); 67 | } 68 | 69 | // Write header 70 | for (int c = 0; c < _columnNames.Length; c++) 71 | { 72 | output.AppendFormat(formatStrings[c], _columnNames[c]); 73 | } 74 | 75 | output.AppendLine(); 76 | 77 | // Write separator 78 | for (int c = 0; c < _columnNames.Length; c++) 79 | { 80 | output.AppendFormat(formatStrings[c], new string('-', _columnNames[c].Length)); 81 | } 82 | 83 | output.AppendLine(); 84 | 85 | // Write rows 86 | foreach (string[] row in _rows) 87 | { 88 | for (int c = 0; c < _columnNames.Length; c++) 89 | { 90 | output.AppendFormat(formatStrings[c], row[c]); 91 | } 92 | 93 | output.AppendLine(); 94 | } 95 | 96 | return output.ToString(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /ShardingPattern/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /The Cloud Design Patterns you didn't know you needed .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/The Cloud Design Patterns you didn't know you needed .pdf -------------------------------------------------------------------------------- /ValetKeyPattern/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "wwwroot/lib" 3 | } 4 | -------------------------------------------------------------------------------- /ValetKeyPattern/AzureStorage/CORSConfigurator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using Microsoft.WindowsAzure.Storage; 3 | using Microsoft.WindowsAzure.Storage.Shared.Protocol; 4 | using System.Collections.Generic; 5 | using ValetKeyPattern.Models; 6 | 7 | namespace ValetKeyPattern.AzureStorage 8 | { 9 | public class CORSConfigurator : ICORSConfigurator 10 | { 11 | private readonly ConnectionStrings _connectionStrings; 12 | 13 | public CORSConfigurator(IOptions connectionStrings) 14 | { 15 | _connectionStrings = connectionStrings.Value; 16 | } 17 | public void EnableCORS() 18 | { 19 | var account = CloudStorageAccount.Parse(_connectionStrings.AzureStorageConnection); 20 | 21 | var blobClient = account.CreateCloudBlobClient(); 22 | 23 | ServiceProperties blobServiceProperties = blobClient.GetServiceProperties(); 24 | 25 | blobServiceProperties.Cors = new CorsProperties(); 26 | 27 | blobServiceProperties.Cors.CorsRules.Add(new CorsRule() 28 | { 29 | AllowedMethods = CorsHttpMethods.Put | CorsHttpMethods.Get | CorsHttpMethods.Head | CorsHttpMethods.Post, 30 | AllowedOrigins = new List() { "*" }, 31 | ExposedHeaders = new List() { "*" }, 32 | AllowedHeaders = new List() { "*" }, 33 | MaxAgeInSeconds = 600 34 | }); 35 | 36 | blobClient.SetServiceProperties(blobServiceProperties); 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ValetKeyPattern/AzureStorage/ICORSConfigurator.cs: -------------------------------------------------------------------------------- 1 | namespace ValetKeyPattern.AzureStorage 2 | { 3 | public interface ICORSConfigurator 4 | { 5 | void EnableCORS(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ValetKeyPattern/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | 7 | namespace ValetKeyPattern.Controllers 8 | { 9 | public class HomeController : Controller 10 | { 11 | public IActionResult Index() 12 | { 13 | return View(); 14 | } 15 | 16 | public IActionResult About() 17 | { 18 | ViewData["Message"] = "Your application description page."; 19 | 20 | return View(); 21 | } 22 | 23 | public IActionResult Contact() 24 | { 25 | ViewData["Message"] = "Your contact page."; 26 | 27 | return View(); 28 | } 29 | 30 | public IActionResult Upload() 31 | { 32 | return View(); 33 | } 34 | 35 | public IActionResult Error() 36 | { 37 | return View(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ValetKeyPattern/Controllers/SaSController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Options; 3 | using Microsoft.WindowsAzure.Storage; 4 | using Microsoft.WindowsAzure.Storage.Blob; 5 | using System; 6 | using System.Globalization; 7 | using ValetKeyPattern.AzureStorage; 8 | using ValetKeyPattern.Models; 9 | 10 | namespace ValetKeyPattern 11 | { 12 | [Route("api/[controller]")] 13 | public class SaSController : Controller 14 | { 15 | private ICORSConfigurator _corsConfigurator; 16 | private readonly ConnectionStrings _connectionStrings; 17 | 18 | public SaSController(ICORSConfigurator corsConfigurator, IOptions connectionStrings) 19 | { 20 | _corsConfigurator = corsConfigurator; 21 | _corsConfigurator.EnableCORS(); 22 | _connectionStrings = connectionStrings.Value; 23 | } 24 | 25 | // GET: api/getkey 26 | [HttpGet] 27 | public string GetKey(string blobName) 28 | { 29 | var account = CloudStorageAccount.Parse(_connectionStrings.AzureStorageConnection); 30 | 31 | var blobClient = account.CreateCloudBlobClient(); 32 | 33 | var container = blobClient.GetContainerReference("pluralsightcontainer"); 34 | container.CreateIfNotExists(); 35 | 36 | // Get a blob reference 37 | CloudBlockBlob blob = container.GetBlockBlobReference(blobName); 38 | 39 | //Create a Shared Access Signature for the blob 40 | var SaS = blob.GetSharedAccessSignature( 41 | new SharedAccessBlobPolicy() 42 | { 43 | Permissions = SharedAccessBlobPermissions.Write, 44 | SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(5), 45 | }); 46 | 47 | return string.Format(CultureInfo.InvariantCulture, "{0}{1}", blob.Uri, SaS); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /ValetKeyPattern/Models/AppSettings.cs: -------------------------------------------------------------------------------- 1 | namespace ValetKeyPattern.Models 2 | { 3 | public class AppSettings 4 | { 5 | public string AzureStorageName { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ValetKeyPattern/Models/ConnectionStrings.cs: -------------------------------------------------------------------------------- 1 | namespace ValetKeyPattern.Models 2 | { 3 | public class ConnectionStrings 4 | { 5 | public string AzureStorageConnection { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ValetKeyPattern/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using System.IO; 3 | 4 | namespace ValetKeyPattern 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | var host = new WebHostBuilder() 11 | .UseKestrel() 12 | .UseContentRoot(Directory.GetCurrentDirectory()) 13 | .UseIISIntegration() 14 | .UseStartup() 15 | .UseApplicationInsights() 16 | .Build(); 17 | 18 | host.Run(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ValetKeyPattern/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:39945/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "ValetKeyPattern": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:39946" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ValetKeyPattern/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Logging; 6 | using ValetKeyPattern.AzureStorage; 7 | using ValetKeyPattern.Models; 8 | 9 | namespace ValetKeyPattern 10 | { 11 | public class Startup 12 | { 13 | public Startup(IHostingEnvironment env) 14 | { 15 | var builder = new ConfigurationBuilder() 16 | .SetBasePath(env.ContentRootPath) 17 | .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) 18 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) 19 | .AddEnvironmentVariables(); 20 | Configuration = builder.Build(); 21 | } 22 | 23 | public IConfigurationRoot Configuration { get; } 24 | 25 | // This method gets called by the runtime. Use this method to add services to the container. 26 | public void ConfigureServices(IServiceCollection services) 27 | { 28 | services.Configure(Configuration.GetSection("ConnectionStrings")); 29 | 30 | services.AddTransient(); 31 | 32 | // Add framework services. 33 | services.AddMvc(); 34 | } 35 | 36 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 37 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 38 | { 39 | loggerFactory.AddConsole(Configuration.GetSection("Logging")); 40 | loggerFactory.AddDebug(); 41 | 42 | if (env.IsDevelopment()) 43 | { 44 | app.UseDeveloperExceptionPage(); 45 | app.UseBrowserLink(); 46 | } 47 | else 48 | { 49 | app.UseExceptionHandler("/Home/Error"); 50 | } 51 | 52 | app.UseStaticFiles(); 53 | 54 | app.UseMvc(routes => 55 | { 56 | routes.MapRoute( 57 | name: "default", 58 | template: "{controller=Home}/{action=Index}/{id?}"); 59 | }); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ValetKeyPattern/ValetKeyPattern.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net461 4 | win7-x86 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ValetKeyPattern/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "About"; 3 | } 4 |

    @ViewData["Title"].

    5 |

    @ViewData["Message"]

    6 | 7 |

    Use this area to provide additional information.

    8 | -------------------------------------------------------------------------------- /ValetKeyPattern/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Contact"; 3 | } 4 |

    @ViewData["Title"].

    5 |

    @ViewData["Message"]

    6 | 7 |
    8 | One Microsoft Way
    9 | Redmond, WA 98052-6399
    10 | P: 11 | 425.555.0100 12 |
    13 | 14 |
    15 | Support: Support@example.com
    16 | Marketing: Marketing@example.com 17 |
    18 | -------------------------------------------------------------------------------- /ValetKeyPattern/Views/Home/Upload.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Upload files"; 3 | } 4 | 5 | 6 |

    Upload files to Azure Storage using SaS

    7 | 8 |
    9 | Upload files 10 |
    11 | Progress:

    12 | 13 | 14 |
    15 | 16 | @section scripts{ 17 | 18 | 73 | } -------------------------------------------------------------------------------- /ValetKeyPattern/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Error"; 3 | } 4 | 5 |

    Error.

    6 |

    An error occurred while processing your request.

    7 | 8 |

    Development Mode

    9 |

    10 | Swapping to Development environment will display more detailed information about the error that occurred. 11 |

    12 |

    13 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 14 |

    15 | -------------------------------------------------------------------------------- /ValetKeyPattern/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet 2 | 3 | 4 | 5 | 6 | 7 | @ViewData["Title"] - ValetKeyPattern 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | @Html.Raw(JavaScriptSnippet.FullScript) 20 | 21 | 22 | 42 |
    43 | @RenderBody() 44 |
    45 |
    46 |

    © 2017 - ValetKeyPattern

    47 |
    48 |
    49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 62 | 68 | 69 | 70 | 71 | @RenderSection("Scripts", required: false) 72 | 73 | 74 | -------------------------------------------------------------------------------- /ValetKeyPattern/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /ValetKeyPattern/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using ValetKeyPattern 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | -------------------------------------------------------------------------------- /ValetKeyPattern/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /ValetKeyPattern/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ValetKeyPattern/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "AzureStorageConnection": "DefaultEndpointsProtocol=https;AccountName=saspluralsight;AccountKey=WCxWWe1EIF8G+rneBwcdOJ6wRjSCq6w0EHByo+TaZlEpIBi+18FFTPOLsssIIcIxqxdwaJOGRA/AyVk1+SoDrA==;" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ValetKeyPattern/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /ValetKeyPattern/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asp.net", 3 | "private": true, 4 | "dependencies": { 5 | "bootstrap": "3.3.7", 6 | "jquery": "2.2.0", 7 | "jquery-validation": "1.14.0", 8 | "jquery-validation-unobtrusive": "3.2.6" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ValetKeyPattern/bundleconfig.json: -------------------------------------------------------------------------------- 1 | // Configure bundling and minification for the project. 2 | // More info at https://go.microsoft.com/fwlink/?LinkId=808241 3 | [ 4 | { 5 | "outputFileName": "wwwroot/css/site.min.css", 6 | // An array of relative input file paths. Globbing patterns supported 7 | "inputFiles": [ 8 | "wwwroot/css/site.css" 9 | ] 10 | }, 11 | { 12 | "outputFileName": "wwwroot/js/site.min.js", 13 | "inputFiles": [ 14 | "wwwroot/js/site.js" 15 | ], 16 | // Optionally specify minification options 17 | "minify": { 18 | "enabled": true, 19 | "renameLocals": true 20 | }, 21 | // Optionally generate .map file 22 | "sourceMap": false 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /ValetKeyPattern/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Wrapping element */ 7 | /* Set some basic padding to keep content from hitting the edges */ 8 | .body-content { 9 | padding-left: 15px; 10 | padding-right: 15px; 11 | } 12 | 13 | /* Set widths on the form inputs since otherwise they're 100% wide */ 14 | input, 15 | select, 16 | textarea { 17 | max-width: 280px; 18 | } 19 | 20 | /* Carousel */ 21 | .carousel-caption p { 22 | font-size: 20px; 23 | line-height: 1.4; 24 | } 25 | 26 | /* Make .svg files in the carousel display properly in older browsers */ 27 | .carousel-inner .item img[src$=".svg"] { 28 | width: 100%; 29 | } 30 | 31 | /* Hide/rearrange for smaller screens */ 32 | @media screen and (max-width: 767px) { 33 | /* Hide captions */ 34 | .carousel-caption { 35 | display: none; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}input,select,textarea{max-width:280px}.carousel-caption p{font-size:20px;line-height:1.4}.carousel-inner .item img[src$=".svg"]{width:100%}@media screen and (max-width:767px){.carousel-caption{display:none}} -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/ValetKeyPattern/wwwroot/favicon.ico -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Write your Javascript code. 2 | -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/ValetKeyPattern/wwwroot/js/site.min.js -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/bootstrap/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bootstrap", 3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", 4 | "keywords": [ 5 | "css", 6 | "js", 7 | "less", 8 | "mobile-first", 9 | "responsive", 10 | "front-end", 11 | "framework", 12 | "web" 13 | ], 14 | "homepage": "http://getbootstrap.com", 15 | "license": "MIT", 16 | "moduleType": "globals", 17 | "main": [ 18 | "less/bootstrap.less", 19 | "dist/js/bootstrap.js" 20 | ], 21 | "ignore": [ 22 | "/.*", 23 | "_config.yml", 24 | "CNAME", 25 | "composer.json", 26 | "CONTRIBUTING.md", 27 | "docs", 28 | "js/tests", 29 | "test-infra" 30 | ], 31 | "dependencies": { 32 | "jquery": "1.9.1 - 3" 33 | }, 34 | "version": "3.3.7", 35 | "_release": "3.3.7", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.3.7", 39 | "commit": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" 40 | }, 41 | "_source": "https://github.com/twbs/bootstrap.git", 42 | "_target": "v3.3.7", 43 | "_originalSource": "bootstrap", 44 | "_direct": true 45 | } -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2016 Twitter, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/ValetKeyPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/ValetKeyPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/ValetKeyPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmaluijb/CloudDesignPatterns/dec728e07b549fb191a1aaef645e25752e06dadc/ValetKeyPattern/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/bootstrap/dist/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/jquery-validation-unobtrusive/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation-unobtrusive", 3 | "version": "3.2.6", 4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive", 5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.", 6 | "main": [ 7 | "jquery.validate.unobtrusive.js" 8 | ], 9 | "ignore": [ 10 | "**/.*", 11 | "*.json", 12 | "*.md", 13 | "*.txt", 14 | "gulpfile.js" 15 | ], 16 | "keywords": [ 17 | "jquery", 18 | "asp.net", 19 | "mvc", 20 | "validation", 21 | "unobtrusive" 22 | ], 23 | "authors": [ 24 | "Microsoft" 25 | ], 26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm", 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git" 30 | }, 31 | "dependencies": { 32 | "jquery-validation": ">=1.8", 33 | "jquery": ">=1.8" 34 | }, 35 | "_release": "3.2.6", 36 | "_resolution": { 37 | "type": "version", 38 | "tag": "v3.2.6", 39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7" 40 | }, 41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git", 42 | "_target": "3.2.6", 43 | "_originalSource": "jquery-validation-unobtrusive" 44 | } -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** Unobtrusive validation support library for jQuery and jQuery Validate 3 | ** Copyright (C) Microsoft Corporation. All rights reserved. 4 | */ 5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery); -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/jquery-validation/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-validation", 3 | "homepage": "http://jqueryvalidation.org/", 4 | "repository": { 5 | "type": "git", 6 | "url": "git://github.com/jzaefferer/jquery-validation.git" 7 | }, 8 | "authors": [ 9 | "Jörn Zaefferer " 10 | ], 11 | "description": "Form validation made easy", 12 | "main": "dist/jquery.validate.js", 13 | "keywords": [ 14 | "forms", 15 | "validation", 16 | "validate" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "test", 24 | "demo", 25 | "lib" 26 | ], 27 | "dependencies": { 28 | "jquery": ">= 1.7.2" 29 | }, 30 | "version": "1.14.0", 31 | "_release": "1.14.0", 32 | "_resolution": { 33 | "type": "version", 34 | "tag": "1.14.0", 35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48" 36 | }, 37 | "_source": "git://github.com/jzaefferer/jquery-validation.git", 38 | "_target": ">=1.8", 39 | "_originalSource": "jquery-validation" 40 | } -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "2.2.0", 16 | "_release": "2.2.0", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "2.2.0", 20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5" 21 | }, 22 | "_source": "git://github.com/jquery/jquery-dist.git", 23 | "_target": "2.2.0", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /ValetKeyPattern/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | --------------------------------------------------------------------------------