├── .dockerignore ├── .gitignore ├── AspNetRunBasic ├── AspNetRunBasic_Retired.csproj ├── Data │ ├── AspnetRunContext.cs │ └── AspnetRunContextSeed.cs ├── Dockerfile ├── Entities │ ├── Category.cs │ └── Product.cs ├── Migrations │ ├── 20190502061258_Initial.Designer.cs │ ├── 20190502061258_Initial.cs │ └── AspnetRunContextModelSnapshot.cs ├── Pages │ ├── Category │ │ ├── Index.cshtml │ │ └── Index.cshtml.cs │ ├── Error.cshtml │ ├── Error.cshtml.cs │ ├── Index.cshtml │ ├── Index.cshtml.cs │ ├── Privacy.cshtml │ ├── Privacy.cshtml.cs │ ├── Product │ │ ├── Create.cshtml │ │ ├── Create.cshtml.cs │ │ ├── Delete.cshtml │ │ ├── Delete.cshtml.cs │ │ ├── Details.cshtml │ │ ├── Details.cshtml.cs │ │ ├── Edit.cshtml │ │ ├── Edit.cshtml.cs │ │ ├── Index.cshtml │ │ └── Index.cshtml.cs │ ├── Shared │ │ ├── _CookieConsentPartial.cshtml │ │ ├── _Layout.cshtml │ │ └── _ValidationScriptsPartial.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── Program.cs ├── Repositories │ ├── IProductRepository.cs │ └── ProductRepository.cs ├── Startup.cs ├── appsettings.Development.json ├── appsettings.json └── wwwroot │ ├── css │ └── site.css │ ├── favicon.ico │ ├── js │ └── site.js │ └── lib │ ├── bootstrap │ ├── LICENSE │ └── dist │ │ ├── css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ └── js │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ └── bootstrap.min.js.map │ ├── jquery-validation-unobtrusive │ ├── LICENSE.txt │ ├── jquery.validate.unobtrusive.js │ └── jquery.validate.unobtrusive.min.js │ ├── jquery-validation │ ├── LICENSE.md │ └── dist │ │ ├── additional-methods.js │ │ ├── additional-methods.min.js │ │ ├── jquery.validate.js │ │ └── jquery.validate.min.js │ └── jquery │ ├── LICENSE.txt │ └── dist │ ├── jquery.js │ ├── jquery.min.js │ └── jquery.min.map ├── AspNetRunBasic_Retired.sln ├── LICENSE ├── README.md └── basicmicroservice ├── Order.Core ├── Entities │ ├── Base │ │ ├── Entity.cs │ │ ├── EntityBase.cs │ │ └── IEntityBase.cs │ └── Order.cs ├── Order.Core.csproj └── Repositories │ ├── Base │ └── IRepository.cs │ └── IOrderRepository.cs ├── Order.Infrastructure ├── Class1.cs └── Order.Infrastructure.csproj ├── basicmicroservice.sln └── src ├── Basket └── Basket.API │ ├── Basket.API.csproj │ ├── Controllers │ └── BasketController.cs │ ├── Entities │ ├── BasketCheckout.cs │ ├── BasketItem.cs │ └── CustomerBasket.cs │ ├── Program.cs │ ├── RabbitMq │ ├── EventBusRabbitMQPublisher.cs │ ├── IRabbitMQConnection.cs │ └── RabbitMQConnection.cs │ ├── Repositories │ ├── Interface │ │ └── IBasketRepository.cs │ └── RedisBasketRepository.cs │ ├── Service │ └── BasketService.cs │ ├── Startup.cs │ ├── appsettings.Development.json │ └── appsettings.json ├── Catalog └── Catalog.API │ ├── Catalog.API.csproj │ ├── Controllers │ └── CatalogController.cs │ ├── Data │ ├── CatalogContext.cs │ └── CatalogContextSeed.cs │ ├── Entities │ ├── Category.cs │ └── Product.cs │ ├── Migrations │ ├── 20200401150236_initial.Designer.cs │ ├── 20200401150236_initial.cs │ └── CatalogContextModelSnapshot.cs │ ├── Program.cs │ ├── Repositories │ ├── Interfaces │ │ └── IProductRepository.cs │ └── ProductRepository.cs │ ├── Startup.cs │ ├── appsettings.Development.json │ └── appsettings.json ├── Order ├── Order.API │ ├── Controllers │ │ └── OrderController.cs │ ├── Order.API.csproj │ ├── Program.cs │ ├── RabbitMq │ │ ├── EventBusRabbitMQConsumer.cs │ │ ├── IRabbitMQConnection.cs │ │ └── RabbitMQConnection.cs │ ├── Startup.cs │ ├── appsettings.Development.json │ └── appsettings.json └── Order.Infrastructure │ ├── Data │ ├── OrderContext.cs │ └── OrderContextSeed.cs │ ├── Order.Infrastructure.csproj │ └── Repository │ ├── Base │ └── Repository.cs │ └── OrderRepository.cs ├── shipment └── Shipment.API │ ├── Controllers │ ├── BooksController.cs │ └── ShipmentController.cs │ ├── Entities │ └── Book.cs │ ├── Program.cs │ ├── Services │ └── BookService.cs │ ├── Settings │ └── BookstoreDatabaseSettings.cs │ ├── Shipment.API.csproj │ ├── Startup.cs │ ├── appsettings.Development.json │ └── appsettings.json └── webui └── ShopApp ├── Pages ├── Error.cshtml ├── Error.cshtml.cs ├── Index.cshtml ├── Index.cshtml.cs ├── Privacy.cshtml ├── Privacy.cshtml.cs ├── Shared │ ├── _Layout.cshtml │ └── _ValidationScriptsPartial.cshtml ├── _ViewImports.cshtml └── _ViewStart.cshtml ├── Program.cs ├── ShopApp.csproj ├── Startup.cs ├── appsettings.Development.json ├── appsettings.json └── wwwroot ├── css └── site.css ├── favicon.ico ├── js └── site.js └── lib ├── bootstrap ├── LICENSE └── dist │ ├── css │ ├── bootstrap-grid.css │ ├── bootstrap-grid.css.map │ ├── bootstrap-grid.min.css │ ├── bootstrap-grid.min.css.map │ ├── bootstrap-reboot.css │ ├── bootstrap-reboot.css.map │ ├── bootstrap-reboot.min.css │ ├── bootstrap-reboot.min.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ └── bootstrap.min.css.map │ └── js │ ├── bootstrap.bundle.js │ ├── bootstrap.bundle.js.map │ ├── bootstrap.bundle.min.js │ ├── bootstrap.bundle.min.js.map │ ├── bootstrap.js │ ├── bootstrap.js.map │ ├── bootstrap.min.js │ └── bootstrap.min.js.map ├── jquery-validation-unobtrusive ├── LICENSE.txt ├── jquery.validate.unobtrusive.js └── jquery.validate.unobtrusive.min.js ├── jquery-validation ├── LICENSE.md └── dist │ ├── additional-methods.js │ ├── additional-methods.min.js │ ├── jquery.validate.js │ └── jquery.validate.min.js └── jquery ├── LICENSE.txt └── dist ├── jquery.js ├── jquery.min.js └── jquery.min.map /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /AspNetRunBasic/AspNetRunBasic_Retired.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | cfcaf7bb-815b-4e0e-b5d8-6345624b1f7f 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | all 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AspNetRunBasic/Data/AspnetRunContext.cs: -------------------------------------------------------------------------------- 1 | using AspNetRunBasic.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace AspNetRunBasic.Data 5 | { 6 | public class AspnetRunContext : DbContext 7 | { 8 | public AspnetRunContext(DbContextOptions options) 9 | : base(options) 10 | { 11 | } 12 | 13 | public DbSet Products { get; set; } 14 | public DbSet Categories { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /AspNetRunBasic/Data/AspnetRunContextSeed.cs: -------------------------------------------------------------------------------- 1 | using AspNetRunBasic.Entities; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace AspNetRunBasic.Data 9 | { 10 | public class AspnetRunContextSeed 11 | { 12 | public static async Task SeedAsync(AspnetRunContext aspnetrunContext, ILoggerFactory loggerFactory, int? retry = 0) 13 | { 14 | int retryForAvailability = retry.Value; 15 | 16 | try 17 | { 18 | // TODO: Only run this if using a real database 19 | // aspnetrunContext.Database.Migrate(); 20 | // aspnetrunContext.Database.EnsureCreated(); 21 | 22 | if (!aspnetrunContext.Categories.Any()) 23 | { 24 | aspnetrunContext.Categories.AddRange(GetPreconfiguredCategories()); 25 | await aspnetrunContext.SaveChangesAsync(); 26 | } 27 | 28 | if (!aspnetrunContext.Products.Any()) 29 | { 30 | aspnetrunContext.Products.AddRange(GetPreconfiguredProducts()); 31 | await aspnetrunContext.SaveChangesAsync(); 32 | } 33 | } 34 | catch (Exception exception) 35 | { 36 | if (retryForAvailability < 10) 37 | { 38 | retryForAvailability++; 39 | var log = loggerFactory.CreateLogger(); 40 | log.LogError(exception.Message); 41 | await SeedAsync(aspnetrunContext, loggerFactory, retryForAvailability); 42 | } 43 | throw; 44 | } 45 | } 46 | 47 | private static IEnumerable GetPreconfiguredCategories() 48 | { 49 | return new List() 50 | { 51 | new Category() { Name = "Phone", Description = "Smart Phones" }, 52 | new Category() { Name = "TV", Description = "Television" } 53 | }; 54 | } 55 | 56 | private static IEnumerable GetPreconfiguredProducts() 57 | { 58 | return new List() 59 | { 60 | new Product() { Name = "IPhone X", Description = "IPhone X Well Done", CategoryId = 1 }, 61 | new Product() { Name = "Samsung 10", Description = "Samsung X Well Done", CategoryId = 1 }, 62 | new Product() { Name = "LG 5", Description = "LG 5 Well Done", CategoryId = 1 }, 63 | new Product() { Name = "Huawei Plus", Description = "Huawei X Well Done", CategoryId = 2 } 64 | }; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /AspNetRunBasic/Dockerfile: -------------------------------------------------------------------------------- 1 | #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. 2 | 3 | FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base 4 | WORKDIR /app 5 | EXPOSE 80 6 | EXPOSE 443 7 | 8 | FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build 9 | WORKDIR /src 10 | COPY ["/AspNetRunBasic.csproj", "AspNetRunBasic/"] 11 | RUN dotnet restore "AspNetRunBasic/AspNetRunBasic.csproj" 12 | COPY . . 13 | WORKDIR "/AspNetRunBasic" 14 | RUN dotnet build "AspNetRunBasic.csproj" -c Release -o /app/build 15 | 16 | FROM build AS publish 17 | RUN dotnet publish "AspNetRunBasic.csproj" -c Release -o /app/publish 18 | 19 | FROM base AS final 20 | WORKDIR /app 21 | COPY --from=publish /app/publish . 22 | ENTRYPOINT ["dotnet", "AspNetRunBasic.dll"] -------------------------------------------------------------------------------- /AspNetRunBasic/Entities/Category.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace AspNetRunBasic.Entities 8 | { 9 | public class Category 10 | { 11 | public int Id { get; set; } 12 | 13 | [Required, StringLength(80)] 14 | public string Name { get; set; } 15 | 16 | public string Description { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /AspNetRunBasic/Entities/Product.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace AspNetRunBasic.Entities 4 | { 5 | public class Product 6 | { 7 | public int Id { get; set; } 8 | 9 | [Required, StringLength(80)] 10 | public string Name { get; set; } 11 | 12 | [Required, StringLength(255)] 13 | public string Description { get; set; } 14 | 15 | public int UnitPrice { get; set; } 16 | 17 | public int CategoryId { get; set; } 18 | public Category Category { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /AspNetRunBasic/Migrations/20190502061258_Initial.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using AspNetRunBasic.Data; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace AspNetRunBasic.Migrations 10 | { 11 | [DbContext(typeof(AspnetRunContext))] 12 | [Migration("20190502061258_Initial")] 13 | partial class Initial 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("ProductVersion", "3.0.0-preview4.19216.3") 20 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 21 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 22 | 23 | modelBuilder.Entity("AspNetRunBasic.Entities.Category", b => 24 | { 25 | b.Property("Id") 26 | .ValueGeneratedOnAdd() 27 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 28 | 29 | b.Property("Description"); 30 | 31 | b.Property("Name") 32 | .IsRequired() 33 | .HasMaxLength(80); 34 | 35 | b.HasKey("Id"); 36 | 37 | b.ToTable("Categories"); 38 | }); 39 | 40 | modelBuilder.Entity("AspNetRunBasic.Entities.Product", b => 41 | { 42 | b.Property("Id") 43 | .ValueGeneratedOnAdd() 44 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 45 | 46 | b.Property("CategoryId"); 47 | 48 | b.Property("Description") 49 | .IsRequired() 50 | .HasMaxLength(255); 51 | 52 | b.Property("Name") 53 | .IsRequired() 54 | .HasMaxLength(80); 55 | 56 | b.Property("UnitPrice"); 57 | 58 | b.HasKey("Id"); 59 | 60 | b.HasIndex("CategoryId"); 61 | 62 | b.ToTable("Products"); 63 | }); 64 | 65 | modelBuilder.Entity("AspNetRunBasic.Entities.Product", b => 66 | { 67 | b.HasOne("AspNetRunBasic.Entities.Category", "Category") 68 | .WithMany() 69 | .HasForeignKey("CategoryId") 70 | .OnDelete(DeleteBehavior.Cascade) 71 | .IsRequired(); 72 | }); 73 | #pragma warning restore 612, 618 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /AspNetRunBasic/Migrations/20190502061258_Initial.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace AspNetRunBasic.Migrations 5 | { 6 | public partial class Initial : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.CreateTable( 11 | name: "Categories", 12 | columns: table => new 13 | { 14 | Id = table.Column(nullable: false) 15 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 16 | Name = table.Column(maxLength: 80, nullable: false), 17 | Description = table.Column(nullable: true) 18 | }, 19 | constraints: table => 20 | { 21 | table.PrimaryKey("PK_Categories", x => x.Id); 22 | }); 23 | 24 | migrationBuilder.CreateTable( 25 | name: "Products", 26 | columns: table => new 27 | { 28 | Id = table.Column(nullable: false) 29 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 30 | Name = table.Column(maxLength: 80, nullable: false), 31 | Description = table.Column(maxLength: 255, nullable: false), 32 | UnitPrice = table.Column(nullable: false), 33 | CategoryId = table.Column(nullable: false) 34 | }, 35 | constraints: table => 36 | { 37 | table.PrimaryKey("PK_Products", x => x.Id); 38 | table.ForeignKey( 39 | name: "FK_Products_Categories_CategoryId", 40 | column: x => x.CategoryId, 41 | principalTable: "Categories", 42 | principalColumn: "Id", 43 | onDelete: ReferentialAction.Cascade); 44 | }); 45 | 46 | migrationBuilder.CreateIndex( 47 | name: "IX_Products_CategoryId", 48 | table: "Products", 49 | column: "CategoryId"); 50 | } 51 | 52 | protected override void Down(MigrationBuilder migrationBuilder) 53 | { 54 | migrationBuilder.DropTable( 55 | name: "Products"); 56 | 57 | migrationBuilder.DropTable( 58 | name: "Categories"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /AspNetRunBasic/Migrations/AspnetRunContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using AspNetRunBasic.Data; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | 8 | namespace AspNetRunBasic.Migrations 9 | { 10 | [DbContext(typeof(AspnetRunContext))] 11 | partial class AspnetRunContextModelSnapshot : ModelSnapshot 12 | { 13 | protected override void BuildModel(ModelBuilder modelBuilder) 14 | { 15 | #pragma warning disable 612, 618 16 | modelBuilder 17 | .HasAnnotation("ProductVersion", "3.0.0-preview4.19216.3") 18 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 19 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 20 | 21 | modelBuilder.Entity("AspNetRunBasic.Entities.Category", b => 22 | { 23 | b.Property("Id") 24 | .ValueGeneratedOnAdd() 25 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 26 | 27 | b.Property("Description"); 28 | 29 | b.Property("Name") 30 | .IsRequired() 31 | .HasMaxLength(80); 32 | 33 | b.HasKey("Id"); 34 | 35 | b.ToTable("Categories"); 36 | }); 37 | 38 | modelBuilder.Entity("AspNetRunBasic.Entities.Product", b => 39 | { 40 | b.Property("Id") 41 | .ValueGeneratedOnAdd() 42 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 43 | 44 | b.Property("CategoryId"); 45 | 46 | b.Property("Description") 47 | .IsRequired() 48 | .HasMaxLength(255); 49 | 50 | b.Property("Name") 51 | .IsRequired() 52 | .HasMaxLength(80); 53 | 54 | b.Property("UnitPrice"); 55 | 56 | b.HasKey("Id"); 57 | 58 | b.HasIndex("CategoryId"); 59 | 60 | b.ToTable("Products"); 61 | }); 62 | 63 | modelBuilder.Entity("AspNetRunBasic.Entities.Product", b => 64 | { 65 | b.HasOne("AspNetRunBasic.Entities.Category", "Category") 66 | .WithMany() 67 | .HasForeignKey("CategoryId") 68 | .OnDelete(DeleteBehavior.Cascade) 69 | .IsRequired(); 70 | }); 71 | #pragma warning restore 612, 618 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Category/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AspNetRunBasic.Pages.Category.IndexModel 3 | @{ 4 | ViewData["Title"] = "Index"; 5 | } 6 | 7 | 8 |

Category List

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | @foreach (var category in Model.CategoryList) 20 | { 21 | 22 | 23 | 24 | 25 | 26 | } 27 | 28 |
IdNameDescription
@category.Id@category.Name@category.Description
29 | 30 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Category/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AspNetRunBasic.Repositories; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | 9 | namespace AspNetRunBasic.Pages.Category 10 | { 11 | public class IndexModel : PageModel 12 | { 13 | private readonly IProductRepository _productRepository; 14 | 15 | public IndexModel(IProductRepository productRepository) 16 | { 17 | _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); 18 | } 19 | 20 | public IEnumerable CategoryList { get; set; } = new List(); 21 | 22 | public async Task OnGetAsync() 23 | { 24 | CategoryList = await _productRepository.GetCategories(); 25 | return Page(); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ErrorModel 3 | @{ 4 | ViewData["Title"] = "Error"; 5 | } 6 | 7 |

Error.

8 |

An error occurred while processing your request.

9 | 10 | @if (Model.ShowRequestId) 11 | { 12 |

13 | Request ID: @Model.RequestId 14 |

15 | } 16 | 17 |

Development Mode

18 |

19 | Swapping to the Development environment displays detailed information about the error that occurred. 20 |

21 |

22 | The Development environment shouldn't be enabled for deployed applications. 23 | It can result in displaying sensitive information from exceptions to end users. 24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 25 | and restarting the app. 26 |

27 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | 9 | namespace AspNetRunBasic.Pages 10 | { 11 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 12 | public class ErrorModel : PageModel 13 | { 14 | public string RequestId { get; set; } 15 | 16 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 17 | 18 | public void OnGet() 19 | { 20 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | @{ 4 | ViewData["Title"] = "Home page"; 5 | } 6 | 7 |

AspnetRunBasic Repository

8 | 9 |

10 | You can check pages in here Products and Categories. 11 |

12 | 13 |

14 | A starter kit for your next web application. Boilerplate for ASP.NET Core reference application with Entity Framework Core, demonstrating a layered application architecture with DDD best practices. 15 |

16 | 17 |

18 | You can check full documentation and step by step development of 100+ page eBook PDF from here -> http://www.aspnetrun.com/ 19 |

20 | 21 |

22 | ASP.NET Run is a general purpose starter kit application specially designed for new modern web applications. It uses already familiar tools and implements best practices around them to provide you a SOLID development experience. This repository focused on traditional Web Application Development with a single deployment. 23 |

24 | 25 |

26 | The goal for this boilerplate is to demonstrate some of the principles and patterns described in the eBook. Also there are sample projects which is implemented this base repositories and build sample of eCommerce reference application, you can check implementation of repo in this location : run-aspnetcore-basic-realworld 27 |

28 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Mvc.RazorPages; 4 | 5 | namespace AspNetRunBasic.Pages 6 | { 7 | public class IndexModel : PageModel 8 | { 9 | public IndexModel() 10 | { 11 | } 12 | 13 | public async Task OnGet() 14 | { 15 | return Page(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model PrivacyModel 3 | @{ 4 | ViewData["Title"] = "Privacy Policy"; 5 | } 6 |

@ViewData["Title"]

7 | 8 |

Use this page to detail your site's privacy policy.

9 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Privacy.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | 8 | namespace AspNetRunBasic.Pages 9 | { 10 | public class PrivacyModel : PageModel 11 | { 12 | public void OnGet() 13 | { 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Create.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AspNetRunBasic.Pages.Product.CreateModel 3 | @{ 4 | ViewData["Title"] = "Create"; 5 | } 6 | 7 |

Create

8 | 9 |

Product

10 |
11 |
12 |
13 |
14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 |
31 | 32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 |
40 | 41 |
42 | Back to List 43 |
44 | 45 | @section Scripts { 46 | @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} 47 | } 48 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Create.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AspNetRunBasic.Repositories; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.AspNetCore.Mvc.Rendering; 9 | 10 | namespace AspNetRunBasic.Pages.Product 11 | { 12 | public class CreateModel : PageModel 13 | { 14 | private readonly IProductRepository _productRepository; 15 | 16 | public CreateModel(IProductRepository productRepository) 17 | { 18 | _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); 19 | } 20 | 21 | public async Task OnGetAsync() 22 | { 23 | var categories = await _productRepository.GetCategories(); 24 | ViewData["CategoryId"] = new SelectList(categories, "Id", "Name"); 25 | return Page(); 26 | } 27 | 28 | [BindProperty] 29 | public Entities.Product Product { get; set; } 30 | 31 | public async Task OnPostAsync() 32 | { 33 | if (!ModelState.IsValid) 34 | { 35 | return Page(); 36 | } 37 | 38 | Product = await _productRepository.AddAsync(Product); 39 | return RedirectToPage("./Index"); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Delete.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AspNetRunBasic.Pages.Product.DeleteModel 3 | @{ 4 | ViewData["Title"] = "Delete"; 5 | } 6 | 7 |

Delete

8 | 9 |

Are you sure you want to delete this?

10 |
11 |

Product

12 |
13 |
14 |
15 | @Html.DisplayNameFor(model => model.Product.Name) 16 |
17 |
18 | @Html.DisplayFor(model => model.Product.Name) 19 |
20 |
21 | @Html.DisplayNameFor(model => model.Product.Description) 22 |
23 |
24 | @Html.DisplayFor(model => model.Product.Description) 25 |
26 |
27 | @Html.DisplayNameFor(model => model.Product.UnitPrice) 28 |
29 |
30 | @Html.DisplayFor(model => model.Product.UnitPrice) 31 |
32 |
33 | @Html.DisplayNameFor(model => model.Product.Category) 34 |
35 |
36 | @Html.DisplayFor(model => model.Product.Category.Name) 37 |
38 |
39 | 40 |
41 | 42 | | 43 | Back to List 44 |
45 |
-------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Delete.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AspNetRunBasic.Repositories; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | 9 | namespace AspNetRunBasic.Pages.Product 10 | { 11 | public class DeleteModel : PageModel 12 | { 13 | private readonly IProductRepository _productRepository; 14 | 15 | public DeleteModel(IProductRepository productRepository) 16 | { 17 | _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); 18 | } 19 | 20 | [BindProperty] 21 | public Entities.Product Product { get; set; } 22 | 23 | public async Task OnGetAsync(int? productId) 24 | { 25 | if (productId == null) 26 | { 27 | return NotFound(); 28 | } 29 | 30 | Product = await _productRepository.GetProductByIdAsync(productId.Value); 31 | if (Product == null) 32 | { 33 | return NotFound(); 34 | } 35 | return Page(); 36 | } 37 | 38 | public async Task OnPostAsync(int? productId) 39 | { 40 | if (productId == null) 41 | { 42 | return NotFound(); 43 | } 44 | 45 | await _productRepository.DeleteAsync(Product); 46 | return RedirectToPage("./Index"); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Details.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AspNetRunBasic.Pages.Product.DetailsModel 3 | @{ 4 | ViewData["Title"] = "Details"; 5 | } 6 | 7 |

Details

8 | 9 |
10 |

Product

11 |
12 |
13 |
14 | @Html.DisplayNameFor(model => model.Product.Name) 15 |
16 |
17 | @Html.DisplayFor(model => model.Product.Name) 18 |
19 |
20 | @Html.DisplayNameFor(model => model.Product.Description) 21 |
22 |
23 | @Html.DisplayFor(model => model.Product.Description) 24 |
25 |
26 | @Html.DisplayNameFor(model => model.Product.UnitPrice) 27 |
28 |
29 | @Html.DisplayFor(model => model.Product.UnitPrice) 30 |
31 |
32 | @Html.DisplayNameFor(model => model.Product.Category) 33 |
34 |
35 | @Html.DisplayFor(model => model.Product.Category.Name) 36 |
37 |
38 |
39 |
40 | Edit | 41 | Back to List 42 |
43 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Details.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AspNetRunBasic.Repositories; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | 9 | namespace AspNetRunBasic.Pages.Product 10 | { 11 | public class DetailsModel : PageModel 12 | { 13 | private readonly IProductRepository _productRepository; 14 | 15 | public DetailsModel(IProductRepository productRepository) 16 | { 17 | _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); 18 | } 19 | 20 | public Entities.Product Product { get; set; } 21 | 22 | public async Task OnGetAsync(int? productId) 23 | { 24 | if (productId == null) 25 | { 26 | return NotFound(); 27 | } 28 | 29 | Product = await _productRepository.GetProductByIdAsync(productId.Value); 30 | if (Product == null) 31 | { 32 | return NotFound(); 33 | } 34 | return Page(); 35 | } 36 | 37 | } 38 | } -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Edit.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AspNetRunBasic.Pages.Product.EditModel 3 | @{ 4 | ViewData["Title"] = "Edit"; 5 | } 6 | 7 |

Edit

8 | 9 |

Product

10 |
11 |
12 |
13 |
14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 | 31 |
32 | 33 | 34 | 35 |
36 | 37 | 38 |
39 | 40 |
41 |
42 |
43 |
44 | 45 |
46 | Back to List 47 |
48 | 49 | @section Scripts { 50 | @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} 51 | } 52 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Edit.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AspNetRunBasic.Repositories; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.AspNetCore.Mvc.Rendering; 9 | using Microsoft.EntityFrameworkCore; 10 | 11 | namespace AspNetRunBasic.Pages.Product 12 | { 13 | public class EditModel : PageModel 14 | { 15 | private readonly IProductRepository _productRepository; 16 | 17 | public EditModel(IProductRepository productRepository) 18 | { 19 | _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); 20 | } 21 | 22 | 23 | [BindProperty] 24 | public Entities.Product Product { get; set; } 25 | 26 | public async Task OnGetAsync(int? productId) 27 | { 28 | if (productId == null) 29 | { 30 | return NotFound(); 31 | } 32 | 33 | Product = await _productRepository.GetProductByIdAsync(productId.Value); 34 | if (Product == null) 35 | { 36 | return NotFound(); 37 | } 38 | 39 | ViewData["CategoryId"] = new SelectList(await _productRepository.GetCategories(), "Id", "Name"); 40 | return Page(); 41 | } 42 | 43 | public async Task OnPostAsync() 44 | { 45 | if (!ModelState.IsValid) 46 | { 47 | return Page(); 48 | } 49 | 50 | try 51 | { 52 | await _productRepository.UpdateAsync(Product); 53 | } 54 | catch (DbUpdateConcurrencyException) 55 | { 56 | if (!ProductExists(Product.Id)) 57 | { 58 | return NotFound(); 59 | } 60 | else 61 | { 62 | throw; 63 | } 64 | } 65 | return RedirectToPage("./Index"); 66 | } 67 | 68 | private bool ProductExists(int id) 69 | { 70 | var product = _productRepository.GetProductByIdAsync(id); 71 | return product != null; 72 | } 73 | 74 | } 75 | } -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model AspNetRunBasic.Pages.Product.IndexModel 3 | 4 | @{ 5 | ViewData["Title"] = "Index"; 6 | } 7 | 8 |

Product List

9 | 10 |
11 |
12 |
13 | 14 | 15 | 18 | 19 |
20 |
21 |
22 | 23 |

24 | Create New 25 |

26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | @foreach (var product in Model.ProductList) 39 | { 40 | 41 | 42 | 43 | 44 | 45 | 62 | 63 | } 64 | 65 |
IdNameUnitPriceCategoryAction
@product.Id@product.Name@product.UnitPrice@product.Category.Name 46 | 49 | Details 50 | 51 | 54 | Edit 55 | 56 | 59 | Delete 60 | 61 |
66 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Product/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AspNetRunBasic.Repositories; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | 9 | namespace AspNetRunBasic.Pages.Product 10 | { 11 | public class IndexModel : PageModel 12 | { 13 | private readonly IProductRepository _productRepository; 14 | 15 | public IndexModel(IProductRepository productRepository) 16 | { 17 | _productRepository = productRepository ?? throw new ArgumentNullException(nameof(productRepository)); 18 | } 19 | 20 | public IEnumerable ProductList { get; set; } = new List(); 21 | 22 | [BindProperty(SupportsGet = true)] 23 | public string SearchTerm { get; set; } 24 | 25 | public async Task OnGetAsync() 26 | { 27 | ProductList = await _productRepository.GetProductByNameAsync(SearchTerm); 28 | return Page(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Shared/_CookieConsentPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Http.Features 2 | 3 | @{ 4 | var consentFeature = Context.Features.Get(); 5 | var showBanner = !consentFeature?.CanTrack ?? false; 6 | var cookieString = consentFeature?.CreateConsentCookie(); 7 | } 8 | 9 | @if (showBanner) 10 | { 11 | 17 | 25 | } 26 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - AspNetRunBasic 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 | 21 |
22 | 47 |
48 |
49 | 50 |
51 | @RenderBody() 52 |
53 |
54 | 55 |
56 |
57 | © 2019 - AspNetRunBasic - Privacy 58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 72 | 78 | 79 | 80 | 81 | @RenderSection("Scripts", required: false) 82 | 83 | 84 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using AspNetRunBasic 2 | @namespace AspNetRunBasic.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /AspNetRunBasic/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /AspNetRunBasic/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using AspNetRunBasic.Data; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace AspNetRunBasic 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | var host = CreateHostBuilder(args).Build(); 15 | SeedDatabase(host); 16 | host.Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | 26 | private static void SeedDatabase(IHost host) 27 | { 28 | using (var scope = host.Services.CreateScope()) 29 | { 30 | var services = scope.ServiceProvider; 31 | var loggerFactory = services.GetRequiredService(); 32 | 33 | try 34 | { 35 | var aspnetRunContext = services.GetRequiredService(); 36 | AspnetRunContextSeed.SeedAsync(aspnetRunContext, loggerFactory).Wait(); 37 | } 38 | catch (Exception exception) 39 | { 40 | var logger = loggerFactory.CreateLogger(); 41 | logger.LogError(exception, "An error occurred seeding the DB."); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /AspNetRunBasic/Repositories/IProductRepository.cs: -------------------------------------------------------------------------------- 1 | using AspNetRunBasic.Entities; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace AspNetRunBasic.Repositories 6 | { 7 | public interface IProductRepository 8 | { 9 | Task> GetProductListAsync(); 10 | Task GetProductByIdAsync(int id); 11 | Task> GetProductByNameAsync(string name); 12 | Task> GetProductByCategoryAsync(int categoryId); 13 | Task AddAsync(Product product); 14 | Task UpdateAsync(Product product); 15 | Task DeleteAsync(Product product); 16 | Task> GetCategories(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /AspNetRunBasic/Repositories/ProductRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AspNetRunBasic.Data; 6 | using AspNetRunBasic.Entities; 7 | using Microsoft.EntityFrameworkCore; 8 | 9 | namespace AspNetRunBasic.Repositories 10 | { 11 | public class ProductRepository : IProductRepository 12 | { 13 | protected readonly AspnetRunContext _dbContext; 14 | 15 | public ProductRepository(AspnetRunContext dbContext) 16 | { 17 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); 18 | } 19 | 20 | public async Task> GetProductListAsync() 21 | { 22 | return await _dbContext.Products.ToListAsync(); 23 | } 24 | 25 | public async Task GetProductByIdAsync(int id) 26 | { 27 | return await _dbContext.Products 28 | .Include(p => p.Category) 29 | .FirstOrDefaultAsync(p => p.Id == id); 30 | } 31 | 32 | public async Task> GetProductByNameAsync(string name) 33 | { 34 | return await _dbContext.Products 35 | .Include(p => p.Category) 36 | .Where(p => string.IsNullOrEmpty(name) || p.Name.ToLower().Contains(name.ToLower())) 37 | .OrderBy(p => p.Name) 38 | .ToListAsync(); 39 | } 40 | 41 | public async Task> GetProductByCategoryAsync(int categoryId) 42 | { 43 | return await _dbContext.Products 44 | .Where(x => x.CategoryId == categoryId) 45 | .ToListAsync(); 46 | } 47 | 48 | public async Task AddAsync(Product product) 49 | { 50 | _dbContext.Products.Add(product); 51 | await _dbContext.SaveChangesAsync(); 52 | return product; 53 | } 54 | 55 | public async Task UpdateAsync(Product product) 56 | { 57 | _dbContext.Entry(product).State = EntityState.Modified; 58 | await _dbContext.SaveChangesAsync(); 59 | } 60 | 61 | public async Task DeleteAsync(Product product) 62 | { 63 | _dbContext.Products.Remove(product); 64 | await _dbContext.SaveChangesAsync(); 65 | } 66 | 67 | public async Task> GetCategories() 68 | { 69 | return await _dbContext.Categories.ToListAsync(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /AspNetRunBasic/Startup.cs: -------------------------------------------------------------------------------- 1 | using AspNetRunBasic.Data; 2 | using AspNetRunBasic.Repositories; 3 | using Microsoft.AspNetCore.Builder; 4 | using Microsoft.AspNetCore.Hosting; 5 | using Microsoft.EntityFrameworkCore; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.Hosting; 9 | 10 | namespace AspNetRunBasic 11 | { 12 | public class Startup 13 | { 14 | public Startup(IConfiguration configuration) 15 | { 16 | Configuration = configuration; 17 | } 18 | 19 | public IConfiguration Configuration { get; } 20 | 21 | // This method gets called by the runtime. Use this method to add services to the container. 22 | public void ConfigureServices(IServiceCollection services) 23 | { 24 | #region Database Connection 25 | 26 | // use in-memory database 27 | services.AddDbContext(c => 28 | c.UseInMemoryDatabase("AspnetRunConnection")); 29 | 30 | //// add real database dependecy 31 | //services.AddDbContext(c => 32 | // c.UseSqlServer(Configuration.GetConnectionString("AspnetRunConnection"))); 33 | 34 | #endregion 35 | 36 | #region Dependencies 37 | 38 | // add repository dependecy 39 | services.AddScoped(); 40 | 41 | #endregion 42 | 43 | services.Configure(options => 44 | { 45 | // This lambda determines whether user consent for non-essential cookies is needed for a given request. 46 | options.CheckConsentNeeded = context => true; 47 | }); 48 | 49 | services.AddRazorPages() 50 | .AddNewtonsoftJson(); 51 | } 52 | 53 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 54 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 55 | { 56 | if (env.IsDevelopment()) 57 | { 58 | app.UseDeveloperExceptionPage(); 59 | } 60 | else 61 | { 62 | app.UseExceptionHandler("/Error"); 63 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 64 | app.UseHsts(); 65 | } 66 | 67 | app.UseHttpsRedirection(); 68 | app.UseStaticFiles(); 69 | app.UseCookiePolicy(); 70 | app.UseRouting(); 71 | app.UseAuthorization(); 72 | 73 | app.UseEndpoints(endpoints => 74 | { 75 | endpoints.MapRazorPages(); 76 | }); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /AspNetRunBasic/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /AspNetRunBasic/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "AspnetRunConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=AspnetRunBasic;" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*" 13 | } 14 | -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | 4 | a.navbar-brand { 5 | white-space: normal; 6 | text-align: center; 7 | word-break: break-all; 8 | } 9 | 10 | /* Sticky footer styles 11 | -------------------------------------------------- */ 12 | html { 13 | font-size: 14px; 14 | } 15 | @media (min-width: 768px) { 16 | html { 17 | font-size: 16px; 18 | } 19 | } 20 | 21 | .border-top { 22 | border-top: 1px solid #e5e5e5; 23 | } 24 | .border-bottom { 25 | border-bottom: 1px solid #e5e5e5; 26 | } 27 | 28 | .box-shadow { 29 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 30 | } 31 | 32 | button.accept-policy { 33 | font-size: 1rem; 34 | line-height: inherit; 35 | } 36 | 37 | /* Sticky footer styles 38 | -------------------------------------------------- */ 39 | html { 40 | position: relative; 41 | min-height: 100%; 42 | } 43 | 44 | body { 45 | /* Margin bottom by footer height */ 46 | margin-bottom: 60px; 47 | } 48 | .footer { 49 | position: absolute; 50 | bottom: 0; 51 | width: 100%; 52 | white-space: nowrap; 53 | /* Set the fixed height of the footer here */ 54 | height: 60px; 55 | line-height: 60px; /* Vertically center the text there */ 56 | } 57 | -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnetrun/run-aspnetcore-basics_retired/5ecfd408fa96812b89d5ff558088e83717957fe0/AspNetRunBasic/wwwroot/favicon.ico -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your Javascript code. 5 | -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 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 | -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */ 8 | *, 9 | *::before, 10 | *::after { 11 | box-sizing: border-box; 12 | } 13 | 14 | html { 15 | font-family: sans-serif; 16 | line-height: 1.15; 17 | -webkit-text-size-adjust: 100%; 18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 19 | } 20 | 21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { 22 | display: block; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 28 | font-size: 1rem; 29 | font-weight: 400; 30 | line-height: 1.5; 31 | color: #212529; 32 | text-align: left; 33 | background-color: #fff; 34 | } 35 | 36 | [tabindex="-1"]:focus { 37 | outline: 0 !important; 38 | } 39 | 40 | hr { 41 | box-sizing: content-box; 42 | height: 0; 43 | overflow: visible; 44 | } 45 | 46 | h1, h2, h3, h4, h5, h6 { 47 | margin-top: 0; 48 | margin-bottom: 0.5rem; 49 | } 50 | 51 | p { 52 | margin-top: 0; 53 | margin-bottom: 1rem; 54 | } 55 | 56 | abbr[title], 57 | abbr[data-original-title] { 58 | text-decoration: underline; 59 | -webkit-text-decoration: underline dotted; 60 | text-decoration: underline dotted; 61 | cursor: help; 62 | border-bottom: 0; 63 | -webkit-text-decoration-skip-ink: none; 64 | text-decoration-skip-ink: none; 65 | } 66 | 67 | address { 68 | margin-bottom: 1rem; 69 | font-style: normal; 70 | line-height: inherit; 71 | } 72 | 73 | ol, 74 | ul, 75 | dl { 76 | margin-top: 0; 77 | margin-bottom: 1rem; 78 | } 79 | 80 | ol ol, 81 | ul ul, 82 | ol ul, 83 | ul ol { 84 | margin-bottom: 0; 85 | } 86 | 87 | dt { 88 | font-weight: 700; 89 | } 90 | 91 | dd { 92 | margin-bottom: .5rem; 93 | margin-left: 0; 94 | } 95 | 96 | blockquote { 97 | margin: 0 0 1rem; 98 | } 99 | 100 | b, 101 | strong { 102 | font-weight: bolder; 103 | } 104 | 105 | small { 106 | font-size: 80%; 107 | } 108 | 109 | sub, 110 | sup { 111 | position: relative; 112 | font-size: 75%; 113 | line-height: 0; 114 | vertical-align: baseline; 115 | } 116 | 117 | sub { 118 | bottom: -.25em; 119 | } 120 | 121 | sup { 122 | top: -.5em; 123 | } 124 | 125 | a { 126 | color: #007bff; 127 | text-decoration: none; 128 | background-color: transparent; 129 | } 130 | 131 | a:hover { 132 | color: #0056b3; 133 | text-decoration: underline; 134 | } 135 | 136 | a:not([href]):not([tabindex]) { 137 | color: inherit; 138 | text-decoration: none; 139 | } 140 | 141 | a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { 142 | color: inherit; 143 | text-decoration: none; 144 | } 145 | 146 | a:not([href]):not([tabindex]):focus { 147 | outline: 0; 148 | } 149 | 150 | pre, 151 | code, 152 | kbd, 153 | samp { 154 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 155 | font-size: 1em; 156 | } 157 | 158 | pre { 159 | margin-top: 0; 160 | margin-bottom: 1rem; 161 | overflow: auto; 162 | } 163 | 164 | figure { 165 | margin: 0 0 1rem; 166 | } 167 | 168 | img { 169 | vertical-align: middle; 170 | border-style: none; 171 | } 172 | 173 | svg { 174 | overflow: hidden; 175 | vertical-align: middle; 176 | } 177 | 178 | table { 179 | border-collapse: collapse; 180 | } 181 | 182 | caption { 183 | padding-top: 0.75rem; 184 | padding-bottom: 0.75rem; 185 | color: #6c757d; 186 | text-align: left; 187 | caption-side: bottom; 188 | } 189 | 190 | th { 191 | text-align: inherit; 192 | } 193 | 194 | label { 195 | display: inline-block; 196 | margin-bottom: 0.5rem; 197 | } 198 | 199 | button { 200 | border-radius: 0; 201 | } 202 | 203 | button:focus { 204 | outline: 1px dotted; 205 | outline: 5px auto -webkit-focus-ring-color; 206 | } 207 | 208 | input, 209 | button, 210 | select, 211 | optgroup, 212 | textarea { 213 | margin: 0; 214 | font-family: inherit; 215 | font-size: inherit; 216 | line-height: inherit; 217 | } 218 | 219 | button, 220 | input { 221 | overflow: visible; 222 | } 223 | 224 | button, 225 | select { 226 | text-transform: none; 227 | } 228 | 229 | select { 230 | word-wrap: normal; 231 | } 232 | 233 | button, 234 | [type="button"], 235 | [type="reset"], 236 | [type="submit"] { 237 | -webkit-appearance: button; 238 | } 239 | 240 | button:not(:disabled), 241 | [type="button"]:not(:disabled), 242 | [type="reset"]:not(:disabled), 243 | [type="submit"]:not(:disabled) { 244 | cursor: pointer; 245 | } 246 | 247 | button::-moz-focus-inner, 248 | [type="button"]::-moz-focus-inner, 249 | [type="reset"]::-moz-focus-inner, 250 | [type="submit"]::-moz-focus-inner { 251 | padding: 0; 252 | border-style: none; 253 | } 254 | 255 | input[type="radio"], 256 | input[type="checkbox"] { 257 | box-sizing: border-box; 258 | padding: 0; 259 | } 260 | 261 | input[type="date"], 262 | input[type="time"], 263 | input[type="datetime-local"], 264 | input[type="month"] { 265 | -webkit-appearance: listbox; 266 | } 267 | 268 | textarea { 269 | overflow: auto; 270 | resize: vertical; 271 | } 272 | 273 | fieldset { 274 | min-width: 0; 275 | padding: 0; 276 | margin: 0; 277 | border: 0; 278 | } 279 | 280 | legend { 281 | display: block; 282 | width: 100%; 283 | max-width: 100%; 284 | padding: 0; 285 | margin-bottom: .5rem; 286 | font-size: 1.5rem; 287 | line-height: inherit; 288 | color: inherit; 289 | white-space: normal; 290 | } 291 | 292 | progress { 293 | vertical-align: baseline; 294 | } 295 | 296 | [type="number"]::-webkit-inner-spin-button, 297 | [type="number"]::-webkit-outer-spin-button { 298 | height: auto; 299 | } 300 | 301 | [type="search"] { 302 | outline-offset: -2px; 303 | -webkit-appearance: none; 304 | } 305 | 306 | [type="search"]::-webkit-search-decoration { 307 | -webkit-appearance: none; 308 | } 309 | 310 | ::-webkit-file-upload-button { 311 | font: inherit; 312 | -webkit-appearance: button; 313 | } 314 | 315 | output { 316 | display: inline-block; 317 | } 318 | 319 | summary { 320 | display: list-item; 321 | cursor: pointer; 322 | } 323 | 324 | template { 325 | display: none; 326 | } 327 | 328 | [hidden] { 329 | display: none !important; 330 | } 331 | /*# sourceMappingURL=bootstrap-reboot.css.map */ -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(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 u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=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),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("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 m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(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(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.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)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.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)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.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)}),m.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)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive}); -------------------------------------------------------------------------------- /AspNetRunBasic/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 | -------------------------------------------------------------------------------- /AspNetRunBasic/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 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 | -------------------------------------------------------------------------------- /AspNetRunBasic_Retired.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28803.202 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetRunBasic_Retired", "AspNetRunBasic\AspNetRunBasic_Retired.csproj", "{05D36AAF-146B-46E1-9A17-663F862EDC06}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {05D36AAF-146B-46E1-9A17-663F862EDC06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {05D36AAF-146B-46E1-9A17-663F862EDC06}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {05D36AAF-146B-46E1-9A17-663F862EDC06}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {05D36AAF-146B-46E1-9A17-663F862EDC06}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {7C73BF53-E283-440E-813F-A451DF2EF4CF} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 aspnetrun 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 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Core/Entities/Base/Entity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Order.Core.Entities.Base 6 | { 7 | public abstract class Entity : EntityBase 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Core/Entities/Base/EntityBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Order.Core.Entities.Base 6 | { 7 | public abstract class EntityBase : IEntityBase 8 | { 9 | public virtual TId Id { get; protected set; } 10 | 11 | int? _requestedHashCode; 12 | 13 | public bool IsTransient() 14 | { 15 | return Id.Equals(default(TId)); 16 | } 17 | 18 | public override bool Equals(object obj) 19 | { 20 | if (obj == null || !(obj is EntityBase)) 21 | return false; 22 | 23 | if (ReferenceEquals(this, obj)) 24 | return true; 25 | 26 | if (GetType() != obj.GetType()) 27 | return false; 28 | 29 | var item = (EntityBase)obj; 30 | 31 | if (item.IsTransient() || IsTransient()) 32 | return false; 33 | else 34 | return item == this; 35 | } 36 | 37 | public override int GetHashCode() 38 | { 39 | if (!IsTransient()) 40 | { 41 | if (!_requestedHashCode.HasValue) 42 | _requestedHashCode = Id.GetHashCode() ^ 31; // XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx) 43 | 44 | return _requestedHashCode.Value; 45 | } 46 | else 47 | return base.GetHashCode(); 48 | } 49 | 50 | public static bool operator ==(EntityBase left, EntityBase right) 51 | { 52 | if (Equals(left, null)) 53 | return Equals(right, null) ? true : false; 54 | else 55 | return left.Equals(right); 56 | } 57 | 58 | public static bool operator !=(EntityBase left, EntityBase right) 59 | { 60 | return !(left == right); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Core/Entities/Base/IEntityBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Order.Core.Entities.Base 6 | { 7 | public interface IEntityBase 8 | { 9 | TId Id { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Core/Entities/Order.cs: -------------------------------------------------------------------------------- 1 | using Order.Core.Entities.Base; 2 | 3 | namespace Order.Core.Entities 4 | { 5 | public class Order : Entity 6 | { 7 | public string UserName { get; set; } 8 | public decimal TotalPrice { get; set; } 9 | 10 | // BillingAddress 11 | public string FirstName { get; set; } 12 | public string LastName { get; set; } 13 | public string EmailAddress { get; set; } 14 | public string AddressLine { get; set; } 15 | public string Country { get; set; } 16 | public string State { get; set; } 17 | public string ZipCode { get; set; } 18 | 19 | // Payment 20 | public string CardName { get; set; } 21 | public string CardNumber { get; set; } 22 | public string Expiration { get; set; } 23 | public string CVV { get; set; } 24 | public PaymentMethod PaymentMethod { get; set; } 25 | } 26 | 27 | public enum PaymentMethod 28 | { 29 | CreditCard = 1, 30 | DebitCard = 2, 31 | Paypal = 3 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Core/Order.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Core/Repositories/Base/IRepository.cs: -------------------------------------------------------------------------------- 1 | using Order.Core.Entities.Base; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Linq.Expressions; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Order.Core.Repositories.Base 10 | { 11 | public interface IRepository where T : Entity 12 | { 13 | Task> GetAllAsync(); 14 | Task> GetAsync(Expression> predicate); 15 | Task> GetAsync(Expression> predicate = null, 16 | Func, IOrderedQueryable> orderBy = null, 17 | string includeString = null, 18 | bool disableTracking = true); 19 | Task> GetAsync(Expression> predicate = null, 20 | Func, IOrderedQueryable> orderBy = null, 21 | List>> includes = null, 22 | bool disableTracking = true); 23 | Task GetByIdAsync(int id); 24 | Task AddAsync(T entity); 25 | Task UpdateAsync(T entity); 26 | Task DeleteAsync(T entity); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Core/Repositories/IOrderRepository.cs: -------------------------------------------------------------------------------- 1 | using Order.Core.Repositories.Base; 2 | using Order.Core.Entities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Order.Core.Repositories 9 | { 10 | public interface IOrderRepository : IRepository 11 | { 12 | Task> GetOrderListAsync(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Infrastructure/Class1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Order.Infrastructure 4 | { 5 | public class Class1 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /basicmicroservice/Order.Infrastructure/Order.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /basicmicroservice/basicmicroservice.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29806.167 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B1F80D21-7738-4DA6-B3D1-C5E77F7146E4}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{5AFB00CF-8E6E-4402-8870-05CF483F43BC}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Catalog", "Catalog", "{4F4FB78C-17C7-4726-A65D-C5CA1E40A806}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Basket", "Basket", "{D6F43D19-A527-4BDB-9CF7-2ABB731C1014}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Order", "Order", "{ED7226E2-4D3C-4164-A88C-436845332BC1}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Catalog.API", "src\Catalog\Catalog.API\Catalog.API.csproj", "{C81249E2-63E5-41EC-9A29-C66D622AF86D}" 17 | EndProject 18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WebUI", "WebUI", "{A620B284-D093-4BB9-92B2-8E0FE0B7B24C}" 19 | EndProject 20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiGateway", "ApiGateway", "{652564FB-14BE-4016-BB38-57039BB73B2A}" 21 | EndProject 22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShopApp", "src\webui\ShopApp\ShopApp.csproj", "{B445668C-7C71-469D-9A6A-27C87043EF60}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Order.API", "src\Order\Order.API\Order.API.csproj", "{981A5534-0E42-4DC9-B99C-2A95EAF97ADF}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Basket.API", "src\Basket\Basket.API\Basket.API.csproj", "{A80C8D6B-E128-4ABD-996B-DE9872845A91}" 27 | EndProject 28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Order.Core", "Order.Core\Order.Core.csproj", "{268069EA-D298-4F9A-9C9E-1A823815124B}" 29 | EndProject 30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Order.Infrastructure", "src\order\Order.Infrastructure\Order.Infrastructure.csproj", "{F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}" 31 | EndProject 32 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipment", "Shipment", "{97A43AA5-C1D3-4CB0-B0EB-501A71422A35}" 33 | EndProject 34 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipment.API", "src\shipment\Shipment.API\Shipment.API.csproj", "{3F0400B9-666C-4E0F-9CAD-58C3ED760C76}" 35 | EndProject 36 | Global 37 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 38 | Debug|Any CPU = Debug|Any CPU 39 | Release|Any CPU = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 42 | {C81249E2-63E5-41EC-9A29-C66D622AF86D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {C81249E2-63E5-41EC-9A29-C66D622AF86D}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {C81249E2-63E5-41EC-9A29-C66D622AF86D}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {C81249E2-63E5-41EC-9A29-C66D622AF86D}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {B445668C-7C71-469D-9A6A-27C87043EF60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {B445668C-7C71-469D-9A6A-27C87043EF60}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {B445668C-7C71-469D-9A6A-27C87043EF60}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {B445668C-7C71-469D-9A6A-27C87043EF60}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {A80C8D6B-E128-4ABD-996B-DE9872845A91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {A80C8D6B-E128-4ABD-996B-DE9872845A91}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {A80C8D6B-E128-4ABD-996B-DE9872845A91}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {A80C8D6B-E128-4ABD-996B-DE9872845A91}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {268069EA-D298-4F9A-9C9E-1A823815124B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {268069EA-D298-4F9A-9C9E-1A823815124B}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {268069EA-D298-4F9A-9C9E-1A823815124B}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {268069EA-D298-4F9A-9C9E-1A823815124B}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76}.Release|Any CPU.Build.0 = Release|Any CPU 70 | EndGlobalSection 71 | GlobalSection(SolutionProperties) = preSolution 72 | HideSolutionNode = FALSE 73 | EndGlobalSection 74 | GlobalSection(NestedProjects) = preSolution 75 | {4F4FB78C-17C7-4726-A65D-C5CA1E40A806} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4} 76 | {D6F43D19-A527-4BDB-9CF7-2ABB731C1014} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4} 77 | {ED7226E2-4D3C-4164-A88C-436845332BC1} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4} 78 | {C81249E2-63E5-41EC-9A29-C66D622AF86D} = {4F4FB78C-17C7-4726-A65D-C5CA1E40A806} 79 | {A620B284-D093-4BB9-92B2-8E0FE0B7B24C} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4} 80 | {652564FB-14BE-4016-BB38-57039BB73B2A} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4} 81 | {B445668C-7C71-469D-9A6A-27C87043EF60} = {A620B284-D093-4BB9-92B2-8E0FE0B7B24C} 82 | {981A5534-0E42-4DC9-B99C-2A95EAF97ADF} = {ED7226E2-4D3C-4164-A88C-436845332BC1} 83 | {A80C8D6B-E128-4ABD-996B-DE9872845A91} = {D6F43D19-A527-4BDB-9CF7-2ABB731C1014} 84 | {268069EA-D298-4F9A-9C9E-1A823815124B} = {ED7226E2-4D3C-4164-A88C-436845332BC1} 85 | {F8A541D6-36C6-4CC2-8FE2-804FC7FF4A4B} = {ED7226E2-4D3C-4164-A88C-436845332BC1} 86 | {97A43AA5-C1D3-4CB0-B0EB-501A71422A35} = {B1F80D21-7738-4DA6-B3D1-C5E77F7146E4} 87 | {3F0400B9-666C-4E0F-9CAD-58C3ED760C76} = {97A43AA5-C1D3-4CB0-B0EB-501A71422A35} 88 | EndGlobalSection 89 | GlobalSection(ExtensibilityGlobals) = postSolution 90 | SolutionGuid = {84204196-8211-4BEA-8688-10C3584CADB2} 91 | EndGlobalSection 92 | EndGlobal 93 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Basket.API.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Controllers/BasketController.cs: -------------------------------------------------------------------------------- 1 | using Basket.API.Entities; 2 | using Basket.API.RabbitMq; 3 | using Basket.API.Repositories.Interface; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Extensions.Logging; 6 | using System; 7 | using System.Net; 8 | using System.Security.Claims; 9 | using System.Threading.Tasks; 10 | 11 | namespace Basket.API.Controllers 12 | { 13 | [Route("api/v1/[controller]")] 14 | [ApiController] 15 | public class BasketController : ControllerBase 16 | { 17 | private readonly IBasketRepository _repository; 18 | private readonly EventBusRabbitMQPublisher _eventBus; 19 | private readonly ILogger _logger; 20 | 21 | public BasketController(IBasketRepository repository, EventBusRabbitMQPublisher eventBus, ILogger logger) 22 | { 23 | _repository = repository ?? throw new ArgumentNullException(nameof(repository)); 24 | _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); 25 | _logger = logger ?? throw new ArgumentNullException(nameof(logger)); 26 | } 27 | 28 | [HttpGet("{id}")] 29 | [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] 30 | public async Task> GetBasketByIdAsync(string id) 31 | { 32 | var basket = await _repository.GetBasketAsync(id); 33 | return Ok(basket ?? new CustomerBasket(id)); 34 | } 35 | 36 | [HttpPost] 37 | [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] 38 | public async Task> UpdateBasketAsync([FromBody]CustomerBasket value) 39 | { 40 | return Ok(await _repository.UpdateBasketAsync(value)); 41 | } 42 | 43 | // DELETE api/values/5 44 | [HttpDelete("{id}")] 45 | [ProducesResponseType(typeof(void), (int)HttpStatusCode.OK)] 46 | public async Task DeleteBasketByIdAsync(string id) 47 | { 48 | await _repository.DeleteBasketAsync(id); 49 | } 50 | 51 | [Route("checkout")] 52 | [HttpPost] 53 | [ProducesResponseType((int)HttpStatusCode.Accepted)] 54 | [ProducesResponseType((int)HttpStatusCode.BadRequest)] 55 | public async Task CheckoutAsync([FromBody]BasketCheckout basketCheckout) 56 | { 57 | // remove the basket 58 | // send checkout event to rabbitMq 59 | 60 | var userId = "swn"; // _identityService.GetUserIdentity(); 61 | 62 | var basketRemoved = await _repository.DeleteBasketAsync(userId); 63 | if (!basketRemoved) 64 | { 65 | return BadRequest(); 66 | } 67 | 68 | basketCheckout.RequestId = Guid.NewGuid(); 69 | basketCheckout.Buyer = userId; 70 | basketCheckout.City = "asd"; 71 | basketCheckout.Country = "asd"; 72 | 73 | _eventBus.PublishBasketCheckout("basketCheckoutQueue", basketCheckout); 74 | 75 | // TODO : burayı alttaki gibi yapılacak -- rabbitMQ kısmı ayrı bir class library yapılıp BasketCheckoutAcceptedIntegrationEvent class ı yapılıp 2 tarafta onu kullanacak 76 | 77 | //var userName = this.HttpContext.User.FindFirst(x => x.Type == ClaimTypes.Name).Value; 78 | 79 | //var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, userName, basketCheckout.City, basketCheckout.Street, 80 | // basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName, 81 | // basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket); 82 | 83 | //// Once basket is checkout, sends an integration event to 84 | //// ordering.api to convert basket to order and proceeds with 85 | //// order creation process 86 | //try 87 | //{ 88 | // _eventBus.Publish(eventMessage); 89 | //} 90 | //catch (Exception ex) 91 | //{ 92 | // _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", eventMessage.Id, "asd"); 93 | // throw; 94 | //} 95 | 96 | return Accepted(); 97 | } 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Entities/BasketCheckout.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Basket.API.Entities 4 | { 5 | public class BasketCheckout 6 | { 7 | public string City { get; set; } 8 | public string Street { get; set; } 9 | public string State { get; set; } 10 | public string Country { get; set; } 11 | public string ZipCode { get; set; } 12 | public string CardNumber { get; set; } 13 | public string CardHolderName { get; set; } 14 | public DateTime CardExpiration { get; set; } 15 | public string CardSecurityNumber { get; set; } 16 | public int CardTypeId { get; set; } 17 | public string Buyer { get; set; } 18 | public Guid RequestId { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Entities/BasketItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Basket.API.Entities 8 | { 9 | public class BasketItem : IValidatableObject 10 | { 11 | public string Id { get; set; } 12 | public int ProductId { get; set; } 13 | public string ProductName { get; set; } 14 | public decimal UnitPrice { get; set; } 15 | public decimal OldUnitPrice { get; set; } 16 | public int Quantity { get; set; } 17 | public string PictureUrl { get; set; } 18 | 19 | public IEnumerable Validate(ValidationContext validationContext) 20 | { 21 | var results = new List(); 22 | 23 | if (Quantity < 1) 24 | { 25 | results.Add(new ValidationResult("Invalid number of units", new[] { "Quantity" })); 26 | } 27 | 28 | return results; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Entities/CustomerBasket.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Basket.API.Entities 4 | { 5 | public class CustomerBasket 6 | { 7 | public string BuyerId { get; set; } 8 | 9 | public List Items { get; set; } = new List(); 10 | 11 | public CustomerBasket() 12 | { 13 | 14 | } 15 | 16 | public CustomerBasket(string customerId) 17 | { 18 | BuyerId = customerId; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Basket.API 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/RabbitMq/EventBusRabbitMQPublisher.cs: -------------------------------------------------------------------------------- 1 | using Basket.API.Entities; 2 | using Newtonsoft.Json; 3 | using RabbitMQ.Client; 4 | using RabbitMQ.Client.Events; 5 | using System; 6 | using System.Text; 7 | 8 | namespace Basket.API.RabbitMq 9 | { 10 | // https://github.com/isanka88/Send-and-Receive-Data-in-Asp.net-Core-With-RabbitMQ 11 | // https://stackoverflow.com/questions/43609345/setup-rabbitmq-consumer-in-asp-net-core-application/43610530#comment98659771_43610530 12 | public class EventBusRabbitMQPublisher 13 | { 14 | private readonly IRabbitMQConnection _connection; 15 | 16 | public EventBusRabbitMQPublisher(IRabbitMQConnection connection) 17 | { 18 | _connection = connection ?? throw new ArgumentNullException(nameof(connection)); 19 | } 20 | 21 | public void PublishBasketCheckout(string queueName, BasketCheckout publishModel) 22 | { 23 | using (var channel = _connection.CreateModel()) 24 | { 25 | channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null); 26 | var message = JsonConvert.SerializeObject(publishModel); 27 | var body = Encoding.UTF8.GetBytes(message); 28 | 29 | IBasicProperties properties = channel.CreateBasicProperties(); 30 | properties.Persistent = true; 31 | properties.DeliveryMode = 2; 32 | 33 | channel.ConfirmSelect(); 34 | channel.BasicPublish(exchange: "", routingKey: queueName, mandatory: true, basicProperties: properties, body: body); 35 | channel.WaitForConfirmsOrDie(); 36 | 37 | channel.BasicAcks += (sender, eventArgs) => 38 | { 39 | Console.WriteLine("Sent RabbitMQ"); 40 | //implement ack handle 41 | }; 42 | channel.ConfirmSelect(); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/RabbitMq/IRabbitMQConnection.cs: -------------------------------------------------------------------------------- 1 | using RabbitMQ.Client; 2 | using System; 3 | 4 | namespace Basket.API.RabbitMq 5 | { 6 | public interface IRabbitMQConnection : IDisposable 7 | { 8 | bool IsConnected { get; } 9 | bool TryConnect(); 10 | IModel CreateModel(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/RabbitMq/RabbitMQConnection.cs: -------------------------------------------------------------------------------- 1 | using RabbitMQ.Client; 2 | using RabbitMQ.Client.Events; 3 | using RabbitMQ.Client.Exceptions; 4 | using System; 5 | using System.IO; 6 | using System.Threading; 7 | 8 | namespace Basket.API.RabbitMq 9 | { 10 | public class RabbitMQConnection : IRabbitMQConnection 11 | { 12 | private readonly IConnectionFactory _connectionFactory; 13 | private IConnection _connection; 14 | private bool _disposed; 15 | 16 | public RabbitMQConnection(IConnectionFactory connectionFactory) 17 | { 18 | _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory)); 19 | if (!IsConnected) 20 | { 21 | TryConnect(); 22 | } 23 | } 24 | 25 | public bool IsConnected 26 | { 27 | get 28 | { 29 | return _connection != null && _connection.IsOpen && !_disposed; 30 | } 31 | } 32 | 33 | public bool TryConnect() 34 | { 35 | try 36 | { 37 | _connection = _connectionFactory.CreateConnection(); 38 | } 39 | catch (BrokerUnreachableException) 40 | { 41 | Thread.Sleep(2000); 42 | _connection = _connectionFactory.CreateConnection(); 43 | } 44 | 45 | if (IsConnected) 46 | { 47 | Console.WriteLine($"RabbitMQ persistent connection acquired a connection {_connection.Endpoint.HostName} and is subscribed to failure events"); 48 | return true; 49 | } 50 | else 51 | { 52 | Console.WriteLine("FATAL ERROR: RabbitMQ connections could not be created and opened"); 53 | return false; 54 | } 55 | } 56 | 57 | public IModel CreateModel() 58 | { 59 | if (!IsConnected) 60 | { 61 | throw new InvalidOperationException("No RabbitMQ connections are available to perform this action"); 62 | } 63 | return _connection.CreateModel(); 64 | } 65 | 66 | public void Dispose() 67 | { 68 | if (_disposed) return; 69 | 70 | _disposed = true; 71 | 72 | try 73 | { 74 | _connection.Dispose(); 75 | } 76 | catch (IOException ex) 77 | { 78 | Console.WriteLine(ex.ToString()); 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Repositories/Interface/IBasketRepository.cs: -------------------------------------------------------------------------------- 1 | using Basket.API.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Basket.API.Repositories.Interface 8 | { 9 | public interface IBasketRepository 10 | { 11 | Task GetBasketAsync(string customerId); 12 | IEnumerable GetUsers(); 13 | Task UpdateBasketAsync(CustomerBasket basket); 14 | Task DeleteBasketAsync(string id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Repositories/RedisBasketRepository.cs: -------------------------------------------------------------------------------- 1 | using Basket.API.Entities; 2 | using Basket.API.Repositories.Interface; 3 | using Microsoft.Extensions.Logging; 4 | using Newtonsoft.Json; 5 | using StackExchange.Redis; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | 11 | namespace Basket.API.Repositories 12 | { 13 | // https://dotnetcorecentral.com/blog/redis-cache-in-net-core-docker-container/ 14 | // https://stackexchange.github.io/StackExchange.Redis/Configuration.html 15 | public class RedisBasketRepository : IBasketRepository 16 | { 17 | private readonly ILogger _logger; 18 | private readonly ConnectionMultiplexer _redis; 19 | private readonly IDatabase _database; 20 | 21 | public RedisBasketRepository(ILoggerFactory loggerFactory, ConnectionMultiplexer redis) 22 | { 23 | _logger = loggerFactory.CreateLogger(); 24 | _redis = redis; 25 | _database = redis.GetDatabase(); 26 | } 27 | 28 | public async Task DeleteBasketAsync(string id) 29 | { 30 | return await _database.KeyDeleteAsync(id); 31 | } 32 | 33 | public IEnumerable GetUsers() 34 | { 35 | var server = GetServer(); 36 | var data = server.Keys(); 37 | 38 | return data?.Select(k => k.ToString()); 39 | } 40 | 41 | public async Task GetBasketAsync(string customerId) 42 | { 43 | var data = await _database.StringGetAsync(customerId); 44 | 45 | if (data.IsNullOrEmpty) 46 | { 47 | return null; 48 | } 49 | 50 | return JsonConvert.DeserializeObject(data); 51 | } 52 | 53 | public async Task UpdateBasketAsync(CustomerBasket basket) 54 | { 55 | var created = await _database.StringSetAsync(basket.BuyerId, JsonConvert.SerializeObject(basket)); 56 | 57 | if (!created) 58 | { 59 | _logger.LogInformation("Problem occur persisting the item."); 60 | return null; 61 | } 62 | 63 | _logger.LogInformation("Basket item persisted succesfully."); 64 | 65 | return await GetBasketAsync(basket.BuyerId); 66 | } 67 | 68 | private IServer GetServer() 69 | { 70 | var endpoint = _redis.GetEndPoints(); 71 | return _redis.GetServer(endpoint.First()); 72 | 73 | 74 | //var customerBasket = new CustomerBasket(); 75 | //customerBasket.BuyerId = "swn"; 76 | //customerBasket.Items.Add( 77 | // new BasketItem 78 | // { 79 | // Id = "1", 80 | // ProductId = 2, 81 | // OldUnitPrice = 3, 82 | // PictureUrl = "asd", 83 | // ProductName = "bas", 84 | // Quantity = 3, 85 | // UnitPrice = 4 86 | // } 87 | // ); 88 | 89 | //var ser = JsonConvert.SerializeObject(customerBasket); 90 | //var created = _database.StringSet(customerBasket.BuyerId, ser); 91 | //var getResult = _database.StringGet(customerBasket.BuyerId); 92 | //var newObject = JsonConvert.DeserializeObject(getResult); 93 | } 94 | 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Service/BasketService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Basket.API.Service 7 | { 8 | // https://medium.com/@matthew.bajorek/creating-a-redis-service-in-asp-net-core-2-2-web-api-17b8b5704454 9 | public class BasketService 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Basket.API.RabbitMq; 6 | using Basket.API.Repositories; 7 | using Basket.API.Repositories.Interface; 8 | using Microsoft.AspNetCore.Builder; 9 | using Microsoft.AspNetCore.Hosting; 10 | using Microsoft.AspNetCore.Mvc; 11 | using Microsoft.Extensions.Configuration; 12 | using Microsoft.Extensions.DependencyInjection; 13 | using Microsoft.Extensions.Hosting; 14 | using Microsoft.Extensions.Logging; 15 | using Microsoft.Extensions.Options; 16 | using RabbitMQ.Client; 17 | using StackExchange.Redis; 18 | 19 | namespace Basket.API 20 | { 21 | public class Startup 22 | { 23 | public Startup(IConfiguration configuration) 24 | { 25 | Configuration = configuration; 26 | } 27 | 28 | public IConfiguration Configuration { get; } 29 | 30 | // This method gets called by the runtime. Use this method to add services to the container. 31 | public void ConfigureServices(IServiceCollection services) 32 | { 33 | services.AddControllers(); 34 | 35 | // add redis 36 | services.AddSingleton(sp => 37 | { 38 | var configuration = ConfigurationOptions.Parse(Configuration.GetConnectionString("RedisCache"), true); 39 | return ConnectionMultiplexer.Connect(configuration); 40 | }); 41 | 42 | #region project services 43 | 44 | // add repository dependecy 45 | services.AddScoped(); 46 | 47 | services.AddSingleton(sp => 48 | { 49 | var factory = new ConnectionFactory() 50 | { 51 | HostName = Configuration["EventBusHostName"] 52 | }; 53 | 54 | if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) 55 | { 56 | factory.UserName = Configuration["EventBusUserName"]; 57 | } 58 | 59 | if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) 60 | { 61 | factory.Password = Configuration["EventBusPassword"]; 62 | } 63 | 64 | return new RabbitMQConnection(factory); 65 | }); 66 | 67 | services.AddSingleton(); 68 | 69 | #endregion 70 | } 71 | 72 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 73 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 74 | { 75 | if (env.IsDevelopment()) 76 | { 77 | app.UseDeveloperExceptionPage(); 78 | } 79 | 80 | app.UseRouting(); 81 | 82 | app.UseAuthorization(); 83 | 84 | app.UseEndpoints(endpoints => 85 | { 86 | endpoints.MapControllers(); 87 | }); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /basicmicroservice/src/Basket/Basket.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "RedisCache": "localhost:6379" 4 | }, 5 | 6 | "Logging": { 7 | "LogLevel": { 8 | "Default": "Information", 9 | "Microsoft": "Warning", 10 | "Microsoft.Hosting.Lifetime": "Information" 11 | } 12 | }, 13 | "AllowedHosts": "*", 14 | 15 | "EventBusHostName": "localhost", 16 | "EventBusUserName": "guest", 17 | "EventBusPassword": "guest" 18 | } 19 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Catalog.API.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | all 12 | runtime; build; native; contentfiles; analyzers; buildtransitive 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Controllers/CatalogController.cs: -------------------------------------------------------------------------------- 1 | using Catalog.API.Repositories.Interfaces; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.Extensions.Logging; 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace Catalog.API.Controllers 8 | { 9 | [Route("api/v1/[controller]")] 10 | [ApiController] 11 | public class CatalogController : ControllerBase 12 | { 13 | private readonly IProductRepository _repository; 14 | private readonly ILogger _logger; 15 | 16 | public CatalogController(IProductRepository repository, ILogger logger) 17 | { 18 | _repository = repository ?? throw new ArgumentNullException(nameof(repository)); 19 | _logger = logger ?? throw new ArgumentNullException(nameof(logger)); 20 | } 21 | 22 | [HttpGet] 23 | public async Task GetProducts() 24 | { 25 | var products = await _repository.GetProducts(); 26 | return Ok(products); 27 | } 28 | 29 | [HttpGet("{id}")] 30 | public async Task GetProductById(int id) 31 | { 32 | var productWithCategory = await _repository.GetProductById(id); 33 | 34 | if (productWithCategory == null) 35 | { 36 | return NotFound(); 37 | } 38 | 39 | return Ok(productWithCategory); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Data/CatalogContext.cs: -------------------------------------------------------------------------------- 1 | using Catalog.API.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace Catalog.API.Data 5 | { 6 | public class CatalogContext : DbContext 7 | { 8 | public CatalogContext(DbContextOptions options) 9 | : base(options) 10 | { 11 | } 12 | 13 | public DbSet Products { get; set; } 14 | public DbSet Categories { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Data/CatalogContextSeed.cs: -------------------------------------------------------------------------------- 1 | using Catalog.API.Entities; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Catalog.API.Data 9 | { 10 | public class CatalogContextSeed 11 | { 12 | public static async Task SeedAsync(CatalogContext aspnetrunContext, ILoggerFactory loggerFactory, int? retry = 0) 13 | { 14 | int retryForAvailability = retry.Value; 15 | 16 | try 17 | { 18 | // TODO: Only run this if using a real database 19 | // aspnetrunContext.Database.Migrate(); 20 | // aspnetrunContext.Database.EnsureCreated(); 21 | 22 | if (!aspnetrunContext.Categories.Any()) 23 | { 24 | aspnetrunContext.Categories.AddRange(GetPreconfiguredCategories()); 25 | await aspnetrunContext.SaveChangesAsync(); 26 | } 27 | 28 | if (!aspnetrunContext.Products.Any()) 29 | { 30 | aspnetrunContext.Products.AddRange(GetPreconfiguredProducts()); 31 | await aspnetrunContext.SaveChangesAsync(); 32 | } 33 | } 34 | catch (Exception exception) 35 | { 36 | if (retryForAvailability < 10) 37 | { 38 | retryForAvailability++; 39 | var log = loggerFactory.CreateLogger(); 40 | log.LogError(exception.Message); 41 | await SeedAsync(aspnetrunContext, loggerFactory, retryForAvailability); 42 | } 43 | throw; 44 | } 45 | } 46 | 47 | private static IEnumerable GetPreconfiguredCategories() 48 | { 49 | return new List() 50 | { 51 | new Category() 52 | { 53 | Name = "White Appliances", 54 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat.", 55 | ImageName = "one" 56 | }, 57 | new Category() 58 | { 59 | Name = "Smart Watches", 60 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat.", 61 | ImageName = "two" 62 | }, 63 | new Category() 64 | { 65 | Name = "Home & Kitchen", 66 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat.", 67 | ImageName = "tree" 68 | } 69 | }; 70 | } 71 | 72 | private static IEnumerable GetPreconfiguredProducts() 73 | { 74 | return new List() 75 | { 76 | new Product() 77 | { 78 | Name = "IPhone X", 79 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.", 80 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.", 81 | ImageFile = "product-1.png", 82 | Price = 950.00M, 83 | CategoryId = 1 84 | }, 85 | new Product() 86 | { 87 | Name = "Samsung 10", 88 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.", 89 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.", 90 | ImageFile = "product-2.png", 91 | Price = 840.00M, 92 | CategoryId = 1 93 | }, 94 | new Product() 95 | { 96 | Name = "Huawei Plus", 97 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.", 98 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.", 99 | ImageFile = "product-3.png", 100 | Price = 650.00M, 101 | CategoryId = 2 102 | }, 103 | new Product() 104 | { 105 | Name = "Xiaomi Mi 9", 106 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.", 107 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.", 108 | ImageFile = "product-4.png", 109 | Price = 470.00M, 110 | CategoryId = 1 111 | }, 112 | new Product() 113 | { 114 | Name = "HTC U11+ Plus", 115 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.", 116 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.", 117 | ImageFile = "product-5.png", 118 | Price = 380.00M, 119 | CategoryId = 1 120 | }, 121 | new Product() 122 | { 123 | Name = "LG G7 ThinQ", 124 | Summary = "This phone is the company's biggest change to its flagship smartphone in years. It includes a borderless.", 125 | Description = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, tenetur natus doloremque laborum quos iste ipsum rerum obcaecati impedit odit illo dolorum ab tempora nihil dicta earum fugiat. Temporibus, voluptatibus.", 126 | ImageFile = "product-6.png", 127 | Price = 240.00M, 128 | CategoryId = 1 129 | } 130 | }; 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Entities/Category.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Catalog.API.Entities 4 | { 5 | public class Category 6 | { 7 | public int Id { get; set; } 8 | 9 | [Required, StringLength(80)] 10 | public string Name { get; set; } 11 | public string Description { get; set; } 12 | public string ImageName { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Entities/Product.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Catalog.API.Entities 4 | { 5 | public class Product 6 | { 7 | public int Id { get; set; } 8 | 9 | [Required, StringLength(80)] 10 | public string Name { get; set; } 11 | 12 | public string Summary { get; set; } 13 | public string Description { get; set; } 14 | public string ImageFile { get; set; } 15 | public decimal Price { get; set; } 16 | public int CategoryId { get; set; } 17 | public Category Category { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Migrations/20200401150236_initial.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using Catalog.API.Data; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace Catalog.API.Migrations 10 | { 11 | [DbContext(typeof(CatalogContext))] 12 | [Migration("20200401150236_initial")] 13 | partial class initial 14 | { 15 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 16 | { 17 | #pragma warning disable 612, 618 18 | modelBuilder 19 | .HasAnnotation("ProductVersion", "3.1.3") 20 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 21 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 22 | 23 | modelBuilder.Entity("Catalog.API.Entities.Category", b => 24 | { 25 | b.Property("Id") 26 | .ValueGeneratedOnAdd() 27 | .HasColumnType("int") 28 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 29 | 30 | b.Property("Description") 31 | .HasColumnType("nvarchar(max)"); 32 | 33 | b.Property("ImageName") 34 | .HasColumnType("nvarchar(max)"); 35 | 36 | b.Property("Name") 37 | .IsRequired() 38 | .HasColumnType("nvarchar(80)") 39 | .HasMaxLength(80); 40 | 41 | b.HasKey("Id"); 42 | 43 | b.ToTable("Categories"); 44 | }); 45 | 46 | modelBuilder.Entity("Catalog.API.Entities.Product", b => 47 | { 48 | b.Property("Id") 49 | .ValueGeneratedOnAdd() 50 | .HasColumnType("int") 51 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 52 | 53 | b.Property("CategoryId") 54 | .HasColumnType("int"); 55 | 56 | b.Property("Description") 57 | .HasColumnType("nvarchar(max)"); 58 | 59 | b.Property("ImageFile") 60 | .HasColumnType("nvarchar(max)"); 61 | 62 | b.Property("Name") 63 | .IsRequired() 64 | .HasColumnType("nvarchar(80)") 65 | .HasMaxLength(80); 66 | 67 | b.Property("Price") 68 | .HasColumnType("decimal(18,2)"); 69 | 70 | b.Property("Summary") 71 | .HasColumnType("nvarchar(max)"); 72 | 73 | b.HasKey("Id"); 74 | 75 | b.HasIndex("CategoryId"); 76 | 77 | b.ToTable("Products"); 78 | }); 79 | 80 | modelBuilder.Entity("Catalog.API.Entities.Product", b => 81 | { 82 | b.HasOne("Catalog.API.Entities.Category", "Category") 83 | .WithMany() 84 | .HasForeignKey("CategoryId") 85 | .OnDelete(DeleteBehavior.Cascade) 86 | .IsRequired(); 87 | }); 88 | #pragma warning restore 612, 618 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Migrations/20200401150236_initial.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace Catalog.API.Migrations 4 | { 5 | public partial class initial : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.CreateTable( 10 | name: "Categories", 11 | columns: table => new 12 | { 13 | Id = table.Column(nullable: false) 14 | .Annotation("SqlServer:Identity", "1, 1"), 15 | Name = table.Column(maxLength: 80, nullable: false), 16 | Description = table.Column(nullable: true), 17 | ImageName = table.Column(nullable: true) 18 | }, 19 | constraints: table => 20 | { 21 | table.PrimaryKey("PK_Categories", x => x.Id); 22 | }); 23 | 24 | migrationBuilder.CreateTable( 25 | name: "Products", 26 | columns: table => new 27 | { 28 | Id = table.Column(nullable: false) 29 | .Annotation("SqlServer:Identity", "1, 1"), 30 | Name = table.Column(maxLength: 80, nullable: false), 31 | Summary = table.Column(nullable: true), 32 | Description = table.Column(nullable: true), 33 | ImageFile = table.Column(nullable: true), 34 | Price = table.Column(nullable: false), 35 | CategoryId = table.Column(nullable: false) 36 | }, 37 | constraints: table => 38 | { 39 | table.PrimaryKey("PK_Products", x => x.Id); 40 | table.ForeignKey( 41 | name: "FK_Products_Categories_CategoryId", 42 | column: x => x.CategoryId, 43 | principalTable: "Categories", 44 | principalColumn: "Id", 45 | onDelete: ReferentialAction.Cascade); 46 | }); 47 | 48 | migrationBuilder.CreateIndex( 49 | name: "IX_Products_CategoryId", 50 | table: "Products", 51 | column: "CategoryId"); 52 | } 53 | 54 | protected override void Down(MigrationBuilder migrationBuilder) 55 | { 56 | migrationBuilder.DropTable( 57 | name: "Products"); 58 | 59 | migrationBuilder.DropTable( 60 | name: "Categories"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Migrations/CatalogContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using Catalog.API.Data; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 7 | 8 | namespace Catalog.API.Migrations 9 | { 10 | [DbContext(typeof(CatalogContext))] 11 | partial class CatalogContextModelSnapshot : ModelSnapshot 12 | { 13 | protected override void BuildModel(ModelBuilder modelBuilder) 14 | { 15 | #pragma warning disable 612, 618 16 | modelBuilder 17 | .HasAnnotation("ProductVersion", "3.1.3") 18 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 19 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 20 | 21 | modelBuilder.Entity("Catalog.API.Entities.Category", b => 22 | { 23 | b.Property("Id") 24 | .ValueGeneratedOnAdd() 25 | .HasColumnType("int") 26 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 27 | 28 | b.Property("Description") 29 | .HasColumnType("nvarchar(max)"); 30 | 31 | b.Property("ImageName") 32 | .HasColumnType("nvarchar(max)"); 33 | 34 | b.Property("Name") 35 | .IsRequired() 36 | .HasColumnType("nvarchar(80)") 37 | .HasMaxLength(80); 38 | 39 | b.HasKey("Id"); 40 | 41 | b.ToTable("Categories"); 42 | }); 43 | 44 | modelBuilder.Entity("Catalog.API.Entities.Product", b => 45 | { 46 | b.Property("Id") 47 | .ValueGeneratedOnAdd() 48 | .HasColumnType("int") 49 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 50 | 51 | b.Property("CategoryId") 52 | .HasColumnType("int"); 53 | 54 | b.Property("Description") 55 | .HasColumnType("nvarchar(max)"); 56 | 57 | b.Property("ImageFile") 58 | .HasColumnType("nvarchar(max)"); 59 | 60 | b.Property("Name") 61 | .IsRequired() 62 | .HasColumnType("nvarchar(80)") 63 | .HasMaxLength(80); 64 | 65 | b.Property("Price") 66 | .HasColumnType("decimal(18,2)"); 67 | 68 | b.Property("Summary") 69 | .HasColumnType("nvarchar(max)"); 70 | 71 | b.HasKey("Id"); 72 | 73 | b.HasIndex("CategoryId"); 74 | 75 | b.ToTable("Products"); 76 | }); 77 | 78 | modelBuilder.Entity("Catalog.API.Entities.Product", b => 79 | { 80 | b.HasOne("Catalog.API.Entities.Category", "Category") 81 | .WithMany() 82 | .HasForeignKey("CategoryId") 83 | .OnDelete(DeleteBehavior.Cascade) 84 | .IsRequired(); 85 | }); 86 | #pragma warning restore 612, 618 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Catalog.API.Data; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace Catalog.API 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | var host = CreateHostBuilder(args).Build(); 15 | SeedDatabase(host); 16 | host.Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | 26 | private static void SeedDatabase(IHost host) 27 | { 28 | using (var scope = host.Services.CreateScope()) 29 | { 30 | var services = scope.ServiceProvider; 31 | var loggerFactory = services.GetRequiredService(); 32 | 33 | try 34 | { 35 | var aspnetRunContext = services.GetRequiredService(); 36 | CatalogContextSeed.SeedAsync(aspnetRunContext, loggerFactory).Wait(); 37 | } 38 | catch (Exception exception) 39 | { 40 | var logger = loggerFactory.CreateLogger(); 41 | logger.LogError(exception, "An error occurred seeding the DB."); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Repositories/Interfaces/IProductRepository.cs: -------------------------------------------------------------------------------- 1 | using Catalog.API.Entities; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace Catalog.API.Repositories.Interfaces 6 | { 7 | public interface IProductRepository 8 | { 9 | Task> GetProducts(); 10 | Task GetProductById(int id); 11 | Task> GetProductByName(string name); 12 | Task> GetProductByCategory(int categoryId); 13 | Task> GetCategories(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Repositories/ProductRepository.cs: -------------------------------------------------------------------------------- 1 | using Catalog.API.Data; 2 | using Catalog.API.Entities; 3 | using Catalog.API.Repositories.Interfaces; 4 | using Microsoft.EntityFrameworkCore; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Catalog.API.Repositories 11 | { 12 | public class ProductRepository : IProductRepository 13 | { 14 | protected readonly CatalogContext _dbContext; 15 | 16 | public ProductRepository(CatalogContext dbContext) 17 | { 18 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); 19 | } 20 | 21 | public async Task> GetProducts() 22 | { 23 | return await _dbContext.Products.ToListAsync(); 24 | } 25 | 26 | public async Task GetProductById(int id) 27 | { 28 | return await _dbContext.Products 29 | .Include(p => p.Category) 30 | .FirstOrDefaultAsync(p => p.Id == id); 31 | } 32 | 33 | public async Task> GetProductByName(string name) 34 | { 35 | return await _dbContext.Products 36 | .Include(p => p.Category) 37 | .Where(p => string.IsNullOrEmpty(name) || p.Name.ToLower().Contains(name.ToLower())) 38 | .OrderBy(p => p.Name) 39 | .ToListAsync(); 40 | } 41 | 42 | public async Task> GetProductByCategory(int categoryId) 43 | { 44 | return await _dbContext.Products 45 | .Where(x => x.CategoryId == categoryId) 46 | .ToListAsync(); 47 | } 48 | 49 | public async Task AddAsync(Product product) 50 | { 51 | _dbContext.Products.Add(product); 52 | await _dbContext.SaveChangesAsync(); 53 | return product; 54 | } 55 | 56 | public async Task UpdateAsync(Product product) 57 | { 58 | _dbContext.Entry(product).State = EntityState.Modified; 59 | await _dbContext.SaveChangesAsync(); 60 | } 61 | 62 | public async Task DeleteAsync(Product product) 63 | { 64 | _dbContext.Products.Remove(product); 65 | await _dbContext.SaveChangesAsync(); 66 | } 67 | 68 | public async Task> GetCategories() 69 | { 70 | return await _dbContext.Categories.ToListAsync(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/Startup.cs: -------------------------------------------------------------------------------- 1 | using Catalog.API.Data; 2 | using Catalog.API.Repositories; 3 | using Catalog.API.Repositories.Interfaces; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.EntityFrameworkCore; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Hosting; 10 | 11 | namespace Catalog.API 12 | { 13 | public class Startup 14 | { 15 | public Startup(IConfiguration configuration) 16 | { 17 | Configuration = configuration; 18 | } 19 | 20 | public IConfiguration Configuration { get; } 21 | 22 | // This method gets called by the runtime. Use this method to add services to the container. 23 | public void ConfigureServices(IServiceCollection services) 24 | { 25 | #region database services 26 | 27 | //// use in-memory database 28 | //services.AddDbContext(c => 29 | // c.UseInMemoryDatabase("AspnetRunConnection")); 30 | 31 | // add database dependecy 32 | services.AddDbContext(c => 33 | c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection"))); 34 | 35 | #endregion 36 | 37 | #region project services 38 | 39 | // add repository dependecy 40 | services.AddScoped(); 41 | 42 | #endregion 43 | 44 | services.AddControllers(); 45 | } 46 | 47 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 48 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 49 | { 50 | if (env.IsDevelopment()) 51 | { 52 | app.UseDeveloperExceptionPage(); 53 | } 54 | 55 | app.UseRouting(); 56 | 57 | app.UseAuthorization(); 58 | 59 | app.UseEndpoints(endpoints => 60 | { 61 | endpoints.MapControllers(); 62 | }); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /basicmicroservice/src/Catalog/Catalog.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "CatalogConnection": "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=CatalogDB;" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*" 13 | } 14 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/Controllers/OrderController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace Order.API.Controllers 9 | { 10 | [ApiController] 11 | [Route("[controller]")] 12 | public class OrderController : ControllerBase 13 | { 14 | //private readonly IBasketRepository _repository; 15 | private readonly ILogger _logger; 16 | 17 | //public BasketController(IBasketRepository repository, EventBusRabbitMQPublisher eventBus, ILogger logger) 18 | //{ 19 | // _repository = repository ?? throw new ArgumentNullException(nameof(repository)); 20 | // _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); 21 | // _logger = logger ?? throw new ArgumentNullException(nameof(logger)); 22 | //} 23 | 24 | //[HttpGet("{id}")] 25 | //[ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] 26 | //public async Task> GetBasketByIdAsync(string id) 27 | //{ 28 | // var basket = await _repository.GetBasketAsync(id); 29 | // return Ok(basket ?? new CustomerBasket(id)); 30 | //} 31 | 32 | 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/Order.API.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Order.API 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/RabbitMq/EventBusRabbitMQConsumer.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using RabbitMQ.Client; 3 | using RabbitMQ.Client.Events; 4 | using System; 5 | using System.Text; 6 | 7 | namespace Order.API.RabbitMq 8 | { 9 | public class EventBusRabbitMQConsumer 10 | { 11 | const string QUEUE_NAME = "basketCheckoutQueue"; 12 | 13 | private readonly IRabbitMQConnection _connection; 14 | 15 | public EventBusRabbitMQConsumer(IRabbitMQConnection connection) 16 | { 17 | _connection = connection ?? throw new ArgumentNullException(nameof(connection)); 18 | } 19 | 20 | public void Consume() 21 | { 22 | var channel = _connection.CreateModel(); 23 | channel.QueueDeclare(queue: QUEUE_NAME, durable: false, exclusive: false, autoDelete: false, arguments: null); 24 | 25 | var consumer = new EventingBasicConsumer(channel); 26 | 27 | //Create event when something receive 28 | consumer.Received += ReceivedEvent; 29 | 30 | channel.BasicConsume(queue: QUEUE_NAME, autoAck: true, consumer: consumer); 31 | } 32 | 33 | private void ReceivedEvent(object sender, BasicDeliverEventArgs e) 34 | { 35 | if (e.RoutingKey == QUEUE_NAME) 36 | { 37 | var message = Encoding.UTF8.GetString(e.Body); 38 | BasketCheckout basketCheckout = JsonConvert.DeserializeObject(message); 39 | 40 | // TODO : stuff 41 | } 42 | } 43 | 44 | public void Disconnect() 45 | { 46 | _connection.Dispose(); 47 | } 48 | } 49 | 50 | public class BasketCheckout 51 | { 52 | public string City { get; set; } 53 | public string Street { get; set; } 54 | public string State { get; set; } 55 | public string Country { get; set; } 56 | public string ZipCode { get; set; } 57 | public string CardNumber { get; set; } 58 | public string CardHolderName { get; set; } 59 | public DateTime CardExpiration { get; set; } 60 | public string CardSecurityNumber { get; set; } 61 | public int CardTypeId { get; set; } 62 | public string Buyer { get; set; } 63 | public Guid RequestId { get; set; } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/RabbitMq/IRabbitMQConnection.cs: -------------------------------------------------------------------------------- 1 | using RabbitMQ.Client; 2 | using System; 3 | 4 | namespace Order.API.RabbitMq 5 | { 6 | public interface IRabbitMQConnection : IDisposable 7 | { 8 | bool IsConnected { get; } 9 | bool TryConnect(); 10 | IModel CreateModel(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/RabbitMq/RabbitMQConnection.cs: -------------------------------------------------------------------------------- 1 | using RabbitMQ.Client; 2 | using RabbitMQ.Client.Exceptions; 3 | using System; 4 | using System.IO; 5 | using System.Threading; 6 | 7 | namespace Order.API.RabbitMq 8 | { 9 | public class RabbitMQConnection : IRabbitMQConnection 10 | { 11 | private readonly IConnectionFactory _connectionFactory; 12 | private IConnection _connection; 13 | private bool _disposed; 14 | 15 | public RabbitMQConnection(IConnectionFactory connectionFactory) 16 | { 17 | _connectionFactory = connectionFactory ?? throw new ArgumentNullException(nameof(connectionFactory)); 18 | if (!IsConnected) 19 | { 20 | TryConnect(); 21 | } 22 | } 23 | 24 | public bool IsConnected 25 | { 26 | get 27 | { 28 | return _connection != null && _connection.IsOpen && !_disposed; 29 | } 30 | } 31 | 32 | public bool TryConnect() 33 | { 34 | try 35 | { 36 | _connection = _connectionFactory.CreateConnection(); 37 | } 38 | catch (BrokerUnreachableException) 39 | { 40 | Thread.Sleep(2000); 41 | _connection = _connectionFactory.CreateConnection(); 42 | } 43 | 44 | if (IsConnected) 45 | { 46 | Console.WriteLine($"RabbitMQ persistent connection acquired a connection {_connection.Endpoint.HostName} and is subscribed to failure events"); 47 | return true; 48 | } 49 | else 50 | { 51 | Console.WriteLine("FATAL ERROR: RabbitMQ connections could not be created and opened"); 52 | return false; 53 | } 54 | } 55 | 56 | public IModel CreateModel() 57 | { 58 | if (!IsConnected) 59 | { 60 | throw new InvalidOperationException("No RabbitMQ connections are available to perform this action"); 61 | } 62 | return _connection.CreateModel(); 63 | } 64 | 65 | public void Dispose() 66 | { 67 | if (_disposed) return; 68 | 69 | _disposed = true; 70 | 71 | try 72 | { 73 | _connection.Dispose(); 74 | } 75 | catch (IOException ex) 76 | { 77 | Console.WriteLine(ex.ToString()); 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/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.Hosting; 6 | using Order.API.RabbitMq; 7 | using RabbitMQ.Client; 8 | 9 | namespace Order.API 10 | { 11 | public class Startup 12 | { 13 | public Startup(IConfiguration configuration) 14 | { 15 | Configuration = configuration; 16 | } 17 | 18 | public IConfiguration Configuration { get; } 19 | 20 | // This method gets called by the runtime. Use this method to add services to the container. 21 | public void ConfigureServices(IServiceCollection services) 22 | { 23 | services.AddControllers(); 24 | 25 | #region project services 26 | 27 | // add repository dependecy 28 | 29 | services.AddSingleton(sp => 30 | { 31 | var factory = new ConnectionFactory() 32 | { 33 | HostName = Configuration["EventBusHostName"] 34 | }; 35 | 36 | if (!string.IsNullOrEmpty(Configuration["EventBusUserName"])) 37 | { 38 | factory.UserName = Configuration["EventBusUserName"]; 39 | } 40 | 41 | if (!string.IsNullOrEmpty(Configuration["EventBusPassword"])) 42 | { 43 | factory.Password = Configuration["EventBusPassword"]; 44 | } 45 | 46 | return new RabbitMQConnection(factory); 47 | }); 48 | 49 | services.AddSingleton(); 50 | 51 | #endregion 52 | } 53 | 54 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 55 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 56 | { 57 | if (env.IsDevelopment()) 58 | { 59 | app.UseDeveloperExceptionPage(); 60 | } 61 | 62 | app.UseRouting(); 63 | 64 | app.UseAuthorization(); 65 | 66 | app.UseEndpoints(endpoints => 67 | { 68 | endpoints.MapControllers(); 69 | }); 70 | 71 | //Initilize Rabbit Listener in ApplicationBuilderExtentions 72 | app.UseRabbitListener(); 73 | } 74 | } 75 | 76 | public static class ApplicationBuilderExtentions 77 | { 78 | public static EventBusRabbitMQConsumer Listener { get; set; } 79 | 80 | public static IApplicationBuilder UseRabbitListener(this IApplicationBuilder app) 81 | { 82 | Listener = app.ApplicationServices.GetService(); 83 | var life = app.ApplicationServices.GetService(); 84 | 85 | life.ApplicationStarted.Register(OnStarted); 86 | life.ApplicationStopping.Register(OnStopping); 87 | 88 | return app; 89 | } 90 | 91 | private static void OnStarted() 92 | { 93 | Listener.Consume(); 94 | } 95 | 96 | private static void OnStopping() 97 | { 98 | Listener.Disconnect(); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*", 10 | 11 | "EventBusHostName": "localhost", 12 | "EventBusUserName": "guest", 13 | "EventBusPassword": "guest" 14 | } 15 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.Infrastructure/Data/OrderContext.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Order.Infrastructure.Data 7 | { 8 | // https://www.npgsql.org/efcore/index.html 9 | // https://medium.com/faun/asp-net-core-entity-framework-core-with-postgresql-code-first-d99b909796d7 10 | public class OrderContext : DbContext 11 | { 12 | public OrderContext(DbContextOptions options) : base(options) 13 | { 14 | // TODO : Burdasın -- postresql ayrı class lib olmadı -- o zaman bunu catalog da yap burda sql server olsun 15 | // olmuyor degistir 16 | } 17 | 18 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 19 | => optionsBuilder.UseNpgsql("Host=my_host;Database=my_db;Username=my_user;Password=my_pw"); 20 | 21 | public DbSet Orders { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.Infrastructure/Data/OrderContextSeed.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Order.Infrastructure.Data 9 | { 10 | public class OrderContextSeed 11 | { 12 | public static async Task SeedAsync(OrderContext aspnetrunContext, ILoggerFactory loggerFactory, int? retry = 0) 13 | { 14 | int retryForAvailability = retry.Value; 15 | 16 | try 17 | { 18 | // TODO: Only run this if using a real database 19 | // aspnetrunContext.Database.Migrate(); 20 | // aspnetrunContext.Database.EnsureCreated(); 21 | 22 | if (!aspnetrunContext.Orders.Any()) 23 | { 24 | aspnetrunContext.Orders.AddRange(GetPreconfiguredOrders()); 25 | await aspnetrunContext.SaveChangesAsync(); 26 | } 27 | 28 | } 29 | catch (Exception exception) 30 | { 31 | if (retryForAvailability < 10) 32 | { 33 | retryForAvailability++; 34 | var log = loggerFactory.CreateLogger(); 35 | log.LogError(exception.Message); 36 | await SeedAsync(aspnetrunContext, loggerFactory, retryForAvailability); 37 | } 38 | throw; 39 | } 40 | } 41 | 42 | private static IEnumerable GetPreconfiguredOrders() 43 | { 44 | return new List() 45 | { 46 | new Order.Core.Entities.Order() { FirstName = "swn", LastName = "asd", AddressLine = "bahcelievler" }, 47 | new Order.Core.Entities.Order() { FirstName = "swn2", LastName = "asd2", AddressLine = "bahcelievler2" } 48 | }; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.Infrastructure/Order.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | all 10 | runtime; build; native; contentfiles; analyzers; buildtransitive 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.Infrastructure/Repository/Base/Repository.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Order.Core.Entities.Base; 3 | using Order.Core.Repositories.Base; 4 | using Order.Infrastructure.Data; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Linq.Expressions; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace Order.Infrastructure.Repository.Base 13 | { 14 | public class Repository : IRepository where T : Entity 15 | { 16 | protected readonly OrderContext _dbContext; 17 | 18 | public Repository(OrderContext dbContext) 19 | { 20 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); 21 | } 22 | 23 | public async Task> GetAllAsync() 24 | { 25 | return await _dbContext.Set().ToListAsync(); 26 | } 27 | 28 | public async Task> GetAsync(Expression> predicate) 29 | { 30 | return await _dbContext.Set().Where(predicate).ToListAsync(); 31 | } 32 | 33 | public async Task> GetAsync(Expression> predicate = null, Func, IOrderedQueryable> orderBy = null, string includeString = null, bool disableTracking = true) 34 | { 35 | IQueryable query = _dbContext.Set(); 36 | if (disableTracking) query = query.AsNoTracking(); 37 | 38 | if (!string.IsNullOrWhiteSpace(includeString)) query = query.Include(includeString); 39 | 40 | if (predicate != null) query = query.Where(predicate); 41 | 42 | if (orderBy != null) 43 | return await orderBy(query).ToListAsync(); 44 | return await query.ToListAsync(); 45 | } 46 | 47 | public async Task> GetAsync(Expression> predicate = null, Func, IOrderedQueryable> orderBy = null, List>> includes = null, bool disableTracking = true) 48 | { 49 | IQueryable query = _dbContext.Set(); 50 | if (disableTracking) query = query.AsNoTracking(); 51 | 52 | if (includes != null) query = includes.Aggregate(query, (current, include) => current.Include(include)); 53 | 54 | if (predicate != null) query = query.Where(predicate); 55 | 56 | if (orderBy != null) 57 | return await orderBy(query).ToListAsync(); 58 | return await query.ToListAsync(); 59 | } 60 | 61 | public virtual async Task GetByIdAsync(int id) 62 | { 63 | return await _dbContext.Set().FindAsync(id); 64 | } 65 | 66 | public async Task AddAsync(T entity) 67 | { 68 | _dbContext.Set().Add(entity); 69 | await _dbContext.SaveChangesAsync(); 70 | return entity; 71 | } 72 | 73 | public async Task UpdateAsync(T entity) 74 | { 75 | _dbContext.Entry(entity).State = EntityState.Modified; 76 | await _dbContext.SaveChangesAsync(); 77 | } 78 | 79 | public async Task DeleteAsync(T entity) 80 | { 81 | _dbContext.Set().Remove(entity); 82 | await _dbContext.SaveChangesAsync(); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /basicmicroservice/src/Order/Order.Infrastructure/Repository/OrderRepository.cs: -------------------------------------------------------------------------------- 1 | using Order.Core.Repositories; 2 | using Order.Infrastructure.Data; 3 | using Order.Infrastructure.Repository.Base; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Order.Infrastructure.Repository 10 | { 11 | public class OrderRepository : Repository, IOrderRepository 12 | { 13 | public OrderRepository(OrderContext dbContext) : base(dbContext) 14 | { 15 | } 16 | 17 | public async Task> GetOrderListAsync() 18 | { 19 | // second way 20 | return await GetAllAsync(); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/Controllers/BooksController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Shipment.API.Entities; 3 | using Shipment.API.Services; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace Shipment.API.Controllers 10 | { 11 | [Route("api/[controller]")] 12 | [ApiController] 13 | public class BooksController : ControllerBase 14 | { 15 | private readonly BookService _bookService; 16 | 17 | public BooksController(BookService bookService) 18 | { 19 | _bookService = bookService; 20 | } 21 | 22 | [HttpGet] 23 | public ActionResult> Get() => 24 | _bookService.Get(); 25 | 26 | [HttpGet("{id:length(24)}", Name = "GetBook")] 27 | public ActionResult Get(string id) 28 | { 29 | var book = _bookService.Get(id); 30 | 31 | if (book == null) 32 | { 33 | return NotFound(); 34 | } 35 | 36 | return book; 37 | } 38 | 39 | [HttpPost] 40 | public ActionResult Create(Book book) 41 | { 42 | _bookService.Create(book); 43 | 44 | return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book); 45 | } 46 | 47 | [HttpPut("{id:length(24)}")] 48 | public IActionResult Update(string id, Book bookIn) 49 | { 50 | var book = _bookService.Get(id); 51 | 52 | if (book == null) 53 | { 54 | return NotFound(); 55 | } 56 | 57 | _bookService.Update(id, bookIn); 58 | 59 | return NoContent(); 60 | } 61 | 62 | [HttpDelete("{id:length(24)}")] 63 | public IActionResult Delete(string id) 64 | { 65 | var book = _bookService.Get(id); 66 | 67 | if (book == null) 68 | { 69 | return NotFound(); 70 | } 71 | 72 | _bookService.Remove(book.Id); 73 | 74 | return NoContent(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/Controllers/ShipmentController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Shipment.API.Controllers 8 | { 9 | public class ShipmentController : ControllerBase 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/Entities/Book.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson; 2 | using MongoDB.Bson.Serialization.Attributes; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Shipment.API.Entities 9 | { 10 | public class Book 11 | { 12 | [BsonId] 13 | [BsonRepresentation(BsonType.ObjectId)] 14 | public string Id { get; set; } 15 | 16 | [BsonElement("Name")] 17 | public string BookName { get; set; } 18 | 19 | public decimal Price { get; set; } 20 | 21 | public string Category { get; set; } 22 | 23 | public string Author { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Shipment.API 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/Services/BookService.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | using Shipment.API.Entities; 3 | using Shipment.API.Settings; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace Shipment.API.Services 10 | { 11 | public class BookService 12 | { 13 | private readonly IMongoCollection _books; 14 | 15 | public BookService(IBookstoreDatabaseSettings settings) 16 | { 17 | var client = new MongoClient(settings.ConnectionString); 18 | var database = client.GetDatabase(settings.DatabaseName); 19 | 20 | _books = database.GetCollection(settings.BooksCollectionName); 21 | } 22 | 23 | public List Get() => 24 | _books.Find(book => true).ToList(); 25 | 26 | public Book Get(string id) => 27 | _books.Find(book => book.Id == id).FirstOrDefault(); 28 | 29 | public Book Create(Book book) 30 | { 31 | _books.InsertOne(book); 32 | return book; 33 | } 34 | 35 | public void Update(string id, Book bookIn) => 36 | _books.ReplaceOne(book => book.Id == id, bookIn); 37 | 38 | public void Remove(Book bookIn) => 39 | _books.DeleteOne(book => book.Id == bookIn.Id); 40 | 41 | public void Remove(string id) => 42 | _books.DeleteOne(book => book.Id == id); 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/Settings/BookstoreDatabaseSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace Shipment.API.Settings 7 | { 8 | public class BookstoreDatabaseSettings : IBookstoreDatabaseSettings 9 | { 10 | public string BooksCollectionName { get; set; } 11 | public string ConnectionString { get; set; } 12 | public string DatabaseName { get; set; } 13 | } 14 | 15 | public interface IBookstoreDatabaseSettings 16 | { 17 | string BooksCollectionName { get; set; } 18 | string ConnectionString { get; set; } 19 | string DatabaseName { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/Shipment.API.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/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.AspNetCore.Mvc; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | using Microsoft.Extensions.Logging; 12 | using Microsoft.Extensions.Options; 13 | using Shipment.API.Services; 14 | using Shipment.API.Settings; 15 | 16 | namespace Shipment.API 17 | { 18 | public class Startup 19 | { 20 | public Startup(IConfiguration configuration) 21 | { 22 | Configuration = configuration; 23 | } 24 | 25 | public IConfiguration Configuration { get; } 26 | 27 | // This method gets called by the runtime. Use this method to add services to the container. 28 | public void ConfigureServices(IServiceCollection services) 29 | { 30 | // requires using Microsoft.Extensions.Options 31 | services.Configure( 32 | Configuration.GetSection(nameof(BookstoreDatabaseSettings))); 33 | 34 | services.AddSingleton(sp => 35 | sp.GetRequiredService>().Value); 36 | 37 | services.AddSingleton(); 38 | 39 | services.AddControllers(); 40 | } 41 | 42 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 43 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 44 | { 45 | if (env.IsDevelopment()) 46 | { 47 | app.UseDeveloperExceptionPage(); 48 | } 49 | 50 | app.UseRouting(); 51 | 52 | app.UseAuthorization(); 53 | 54 | app.UseEndpoints(endpoints => 55 | { 56 | endpoints.MapControllers(); 57 | }); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /basicmicroservice/src/shipment/Shipment.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "BookstoreDatabaseSettings": { 3 | "BooksCollectionName": "Books", 4 | "ConnectionString": "mongodb://localhost:27017", 5 | "DatabaseName": "BookstoreDb" 6 | }, 7 | "Logging": { 8 | "LogLevel": { 9 | "Default": "Information", 10 | "Microsoft": "Warning", 11 | "Microsoft.Hosting.Lifetime": "Information" 12 | } 13 | }, 14 | "AllowedHosts": "*" 15 | } 16 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ErrorModel 3 | @{ 4 | ViewData["Title"] = "Error"; 5 | } 6 | 7 |

    Error.

    8 |

    An error occurred while processing your request.

    9 | 10 | @if (Model.ShowRequestId) 11 | { 12 |

    13 | Request ID: @Model.RequestId 14 |

    15 | } 16 | 17 |

    Development Mode

    18 |

    19 | Swapping to the Development environment displays detailed information about the error that occurred. 20 |

    21 |

    22 | The Development environment shouldn't be enabled for deployed applications. 23 | It can result in displaying sensitive information from exceptions to end users. 24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 25 | and restarting the app. 26 |

    27 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.RazorPages; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace ShopApp.Pages 11 | { 12 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 13 | public class ErrorModel : PageModel 14 | { 15 | public string RequestId { get; set; } 16 | 17 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 18 | 19 | private readonly ILogger _logger; 20 | 21 | public ErrorModel(ILogger logger) 22 | { 23 | _logger = logger; 24 | } 25 | 26 | public void OnGet() 27 | { 28 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | @{ 4 | ViewData["Title"] = "Home page"; 5 | } 6 | 7 |
    8 |

    Welcome

    9 |

    Learn about building Web apps with ASP.NET Core.

    10 |
    11 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace ShopApp.Pages 10 | { 11 | public class IndexModel : PageModel 12 | { 13 | private readonly ILogger _logger; 14 | 15 | public IndexModel(ILogger logger) 16 | { 17 | _logger = logger; 18 | } 19 | 20 | public void OnGet() 21 | { 22 | 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model PrivacyModel 3 | @{ 4 | ViewData["Title"] = "Privacy Policy"; 5 | } 6 |

    @ViewData["Title"]

    7 | 8 |

    Use this page to detail your site's privacy policy.

    9 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/Privacy.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace ShopApp.Pages 10 | { 11 | public class PrivacyModel : PageModel 12 | { 13 | private readonly ILogger _logger; 14 | 15 | public PrivacyModel(ILogger logger) 16 | { 17 | _logger = logger; 18 | } 19 | 20 | public void OnGet() 21 | { 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - ShopApp 7 | 8 | 9 | 10 | 11 |
    12 | 31 |
    32 |
    33 |
    34 | @RenderBody() 35 |
    36 |
    37 | 38 |
    39 |
    40 | © 2020 - ShopApp - Privacy 41 |
    42 |
    43 | 44 | 45 | 46 | 47 | 48 | @RenderSection("Scripts", required: false) 49 | 50 | 51 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using ShopApp 2 | @namespace ShopApp.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace ShopApp 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/ShopApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/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.AspNetCore.HttpsPolicy; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | 12 | namespace ShopApp 13 | { 14 | public class Startup 15 | { 16 | public Startup(IConfiguration configuration) 17 | { 18 | Configuration = configuration; 19 | } 20 | 21 | public IConfiguration Configuration { get; } 22 | 23 | // This method gets called by the runtime. Use this method to add services to the container. 24 | public void ConfigureServices(IServiceCollection services) 25 | { 26 | services.AddRazorPages(); 27 | } 28 | 29 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 30 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 31 | { 32 | if (env.IsDevelopment()) 33 | { 34 | app.UseDeveloperExceptionPage(); 35 | } 36 | else 37 | { 38 | app.UseExceptionHandler("/Error"); 39 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 40 | app.UseHsts(); 41 | } 42 | 43 | app.UseHttpsRedirection(); 44 | app.UseStaticFiles(); 45 | 46 | app.UseRouting(); 47 | 48 | app.UseAuthorization(); 49 | 50 | app.UseEndpoints(endpoints => 51 | { 52 | endpoints.MapRazorPages(); 53 | }); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | 4 | a.navbar-brand { 5 | white-space: normal; 6 | text-align: center; 7 | word-break: break-all; 8 | } 9 | 10 | /* Provide sufficient contrast against white background */ 11 | a { 12 | color: #0366d6; 13 | } 14 | 15 | .btn-primary { 16 | color: #fff; 17 | background-color: #1b6ec2; 18 | border-color: #1861ac; 19 | } 20 | 21 | .nav-pills .nav-link.active, .nav-pills .show > .nav-link { 22 | color: #fff; 23 | background-color: #1b6ec2; 24 | border-color: #1861ac; 25 | } 26 | 27 | /* Sticky footer styles 28 | -------------------------------------------------- */ 29 | html { 30 | font-size: 14px; 31 | } 32 | @media (min-width: 768px) { 33 | html { 34 | font-size: 16px; 35 | } 36 | } 37 | 38 | .border-top { 39 | border-top: 1px solid #e5e5e5; 40 | } 41 | .border-bottom { 42 | border-bottom: 1px solid #e5e5e5; 43 | } 44 | 45 | .box-shadow { 46 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 47 | } 48 | 49 | button.accept-policy { 50 | font-size: 1rem; 51 | line-height: inherit; 52 | } 53 | 54 | /* Sticky footer styles 55 | -------------------------------------------------- */ 56 | html { 57 | position: relative; 58 | min-height: 100%; 59 | } 60 | 61 | body { 62 | /* Margin bottom by footer height */ 63 | margin-bottom: 60px; 64 | } 65 | .footer { 66 | position: absolute; 67 | bottom: 0; 68 | width: 100%; 69 | white-space: nowrap; 70 | line-height: 60px; /* Vertically center the text there */ 71 | } 72 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aspnetrun/run-aspnetcore-basics_retired/5ecfd408fa96812b89d5ff558088e83717957fe0/basicmicroservice/src/webui/ShopApp/wwwroot/favicon.ico -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your Javascript code. 5 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 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 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */ 8 | *, 9 | *::before, 10 | *::after { 11 | box-sizing: border-box; 12 | } 13 | 14 | html { 15 | font-family: sans-serif; 16 | line-height: 1.15; 17 | -webkit-text-size-adjust: 100%; 18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 19 | } 20 | 21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { 22 | display: block; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 28 | font-size: 1rem; 29 | font-weight: 400; 30 | line-height: 1.5; 31 | color: #212529; 32 | text-align: left; 33 | background-color: #fff; 34 | } 35 | 36 | [tabindex="-1"]:focus { 37 | outline: 0 !important; 38 | } 39 | 40 | hr { 41 | box-sizing: content-box; 42 | height: 0; 43 | overflow: visible; 44 | } 45 | 46 | h1, h2, h3, h4, h5, h6 { 47 | margin-top: 0; 48 | margin-bottom: 0.5rem; 49 | } 50 | 51 | p { 52 | margin-top: 0; 53 | margin-bottom: 1rem; 54 | } 55 | 56 | abbr[title], 57 | abbr[data-original-title] { 58 | text-decoration: underline; 59 | -webkit-text-decoration: underline dotted; 60 | text-decoration: underline dotted; 61 | cursor: help; 62 | border-bottom: 0; 63 | -webkit-text-decoration-skip-ink: none; 64 | text-decoration-skip-ink: none; 65 | } 66 | 67 | address { 68 | margin-bottom: 1rem; 69 | font-style: normal; 70 | line-height: inherit; 71 | } 72 | 73 | ol, 74 | ul, 75 | dl { 76 | margin-top: 0; 77 | margin-bottom: 1rem; 78 | } 79 | 80 | ol ol, 81 | ul ul, 82 | ol ul, 83 | ul ol { 84 | margin-bottom: 0; 85 | } 86 | 87 | dt { 88 | font-weight: 700; 89 | } 90 | 91 | dd { 92 | margin-bottom: .5rem; 93 | margin-left: 0; 94 | } 95 | 96 | blockquote { 97 | margin: 0 0 1rem; 98 | } 99 | 100 | b, 101 | strong { 102 | font-weight: bolder; 103 | } 104 | 105 | small { 106 | font-size: 80%; 107 | } 108 | 109 | sub, 110 | sup { 111 | position: relative; 112 | font-size: 75%; 113 | line-height: 0; 114 | vertical-align: baseline; 115 | } 116 | 117 | sub { 118 | bottom: -.25em; 119 | } 120 | 121 | sup { 122 | top: -.5em; 123 | } 124 | 125 | a { 126 | color: #007bff; 127 | text-decoration: none; 128 | background-color: transparent; 129 | } 130 | 131 | a:hover { 132 | color: #0056b3; 133 | text-decoration: underline; 134 | } 135 | 136 | a:not([href]):not([tabindex]) { 137 | color: inherit; 138 | text-decoration: none; 139 | } 140 | 141 | a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { 142 | color: inherit; 143 | text-decoration: none; 144 | } 145 | 146 | a:not([href]):not([tabindex]):focus { 147 | outline: 0; 148 | } 149 | 150 | pre, 151 | code, 152 | kbd, 153 | samp { 154 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 155 | font-size: 1em; 156 | } 157 | 158 | pre { 159 | margin-top: 0; 160 | margin-bottom: 1rem; 161 | overflow: auto; 162 | } 163 | 164 | figure { 165 | margin: 0 0 1rem; 166 | } 167 | 168 | img { 169 | vertical-align: middle; 170 | border-style: none; 171 | } 172 | 173 | svg { 174 | overflow: hidden; 175 | vertical-align: middle; 176 | } 177 | 178 | table { 179 | border-collapse: collapse; 180 | } 181 | 182 | caption { 183 | padding-top: 0.75rem; 184 | padding-bottom: 0.75rem; 185 | color: #6c757d; 186 | text-align: left; 187 | caption-side: bottom; 188 | } 189 | 190 | th { 191 | text-align: inherit; 192 | } 193 | 194 | label { 195 | display: inline-block; 196 | margin-bottom: 0.5rem; 197 | } 198 | 199 | button { 200 | border-radius: 0; 201 | } 202 | 203 | button:focus { 204 | outline: 1px dotted; 205 | outline: 5px auto -webkit-focus-ring-color; 206 | } 207 | 208 | input, 209 | button, 210 | select, 211 | optgroup, 212 | textarea { 213 | margin: 0; 214 | font-family: inherit; 215 | font-size: inherit; 216 | line-height: inherit; 217 | } 218 | 219 | button, 220 | input { 221 | overflow: visible; 222 | } 223 | 224 | button, 225 | select { 226 | text-transform: none; 227 | } 228 | 229 | select { 230 | word-wrap: normal; 231 | } 232 | 233 | button, 234 | [type="button"], 235 | [type="reset"], 236 | [type="submit"] { 237 | -webkit-appearance: button; 238 | } 239 | 240 | button:not(:disabled), 241 | [type="button"]:not(:disabled), 242 | [type="reset"]:not(:disabled), 243 | [type="submit"]:not(:disabled) { 244 | cursor: pointer; 245 | } 246 | 247 | button::-moz-focus-inner, 248 | [type="button"]::-moz-focus-inner, 249 | [type="reset"]::-moz-focus-inner, 250 | [type="submit"]::-moz-focus-inner { 251 | padding: 0; 252 | border-style: none; 253 | } 254 | 255 | input[type="radio"], 256 | input[type="checkbox"] { 257 | box-sizing: border-box; 258 | padding: 0; 259 | } 260 | 261 | input[type="date"], 262 | input[type="time"], 263 | input[type="datetime-local"], 264 | input[type="month"] { 265 | -webkit-appearance: listbox; 266 | } 267 | 268 | textarea { 269 | overflow: auto; 270 | resize: vertical; 271 | } 272 | 273 | fieldset { 274 | min-width: 0; 275 | padding: 0; 276 | margin: 0; 277 | border: 0; 278 | } 279 | 280 | legend { 281 | display: block; 282 | width: 100%; 283 | max-width: 100%; 284 | padding: 0; 285 | margin-bottom: .5rem; 286 | font-size: 1.5rem; 287 | line-height: inherit; 288 | color: inherit; 289 | white-space: normal; 290 | } 291 | 292 | progress { 293 | vertical-align: baseline; 294 | } 295 | 296 | [type="number"]::-webkit-inner-spin-button, 297 | [type="number"]::-webkit-outer-spin-button { 298 | height: auto; 299 | } 300 | 301 | [type="search"] { 302 | outline-offset: -2px; 303 | -webkit-appearance: none; 304 | } 305 | 306 | [type="search"]::-webkit-search-decoration { 307 | -webkit-appearance: none; 308 | } 309 | 310 | ::-webkit-file-upload-button { 311 | font: inherit; 312 | -webkit-appearance: button; 313 | } 314 | 315 | output { 316 | display: inline-block; 317 | } 318 | 319 | summary { 320 | display: list-item; 321 | cursor: pointer; 322 | } 323 | 324 | template { 325 | display: none; 326 | } 327 | 328 | [hidden] { 329 | display: none !important; 330 | } 331 | /*# sourceMappingURL=bootstrap-reboot.css.map */ -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(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 u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=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),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("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 m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(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(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.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)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.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)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.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)}),m.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)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive}); -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/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 | -------------------------------------------------------------------------------- /basicmicroservice/src/webui/ShopApp/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 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 | --------------------------------------------------------------------------------