├── .gitignore ├── DotnetDocsShow.Extensions.Validation ├── Customers │ ├── Customer.cs │ ├── CustomerEndpoints.cs │ ├── CustomerService.cs │ ├── CustomerValidation.cs │ └── ICustomerService.cs ├── DotnetDocsShow.Extensions.Validation.csproj ├── IAssemblyMarker.cs ├── Program.cs └── ValidationExtensions.cs ├── DotnetDocsShow.Intro.MinimalApi ├── DotnetDocsShow.Intro.MinimalApi.csproj └── Program.cs ├── DotnetDocsShow.MinimalApiTests.Structured ├── DotnetDocsShow.MinimalApiTests.Structured.csproj ├── EndpointDefinitionExtensions.cs ├── EndpointDefinitions │ ├── CustomerEndpointDefinition.cs │ └── SwaggerEndpointDefinition.cs ├── IEndpointDefinition.cs ├── Models │ └── Customer.cs ├── Program.cs └── Services │ ├── CustomerService.cs │ └── ICustomerService.cs ├── DotnetDocsShow.NewWebApi ├── Controllers │ └── WeatherForecastController.cs ├── DotnetDocsShow.NewWebApi.csproj ├── Program.cs ├── Properties │ └── launchSettings.json ├── WeatherForecast.cs ├── appsettings.Development.json └── appsettings.json ├── DotnetDocsShow.OldWebApi ├── Controllers │ └── WeatherForecastController.cs ├── DotnetDocsShow.OldWebApi.csproj ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── WeatherForecast.cs ├── appsettings.Development.json └── appsettings.json ├── DotnetDocsShow.PerformanceTests ├── DotnetDocsShow.PerformanceTests.csproj └── Program.cs ├── DotnetDocsShow.Structured.Extensions ├── Customers │ ├── Customer.cs │ ├── CustomerEndpoints.cs │ ├── CustomerService.cs │ └── ICustomerService.cs ├── DotnetDocsShow.Structured.Extensions.csproj └── Program.cs ├── DotnetDocsShow.Structured.Mediator ├── DotnetDocsShow.Structured.Mediator.csproj ├── Handlers │ ├── CreateCustomerRequestHandler.cs │ ├── DeleteCustomerByIdRequestHandler.cs │ ├── GetAllCustomersRequestHandler.cs │ └── GetCustomerByIdRequestHandler.cs ├── Models │ └── Customer.cs ├── Program.cs └── Services │ ├── CustomerService.cs │ └── ICustomerService.cs ├── DotnetDocsShow.Structured.Scanning ├── DotnetDocsShow.Structured.Scanning.csproj ├── EndpointDefinitionExtensions.cs ├── EndpointDefinitions │ ├── CustomerEndpointDefinition.cs │ ├── PaymentsEndpointDefinition.cs │ └── SwaggerEndpointDefinition.cs ├── IEndpointDefinition.cs ├── Models │ └── Customer.cs ├── Program.cs └── Services │ ├── CustomerService.cs │ └── ICustomerService.cs ├── DotnetDocsShow.Tests.Integration ├── BroadCustomerEndpointsTests.cs ├── DotnetDocsShow.Tests.Integration.csproj ├── NarrowCustomerEndpointsTests.cs └── TestApplicationFactory.cs ├── DotnetDocsShow.Tests.Unit ├── CustomerEndpointDefinitionTests.cs ├── DotnetDocsShow.Tests.Unit.csproj └── ResultExtensions.cs ├── DotnetDocsShow.Weather.MinimalApi ├── DotnetDocsShow.Weather.MinimalApi.csproj ├── Program.cs ├── WeatherEndpoints.cs ├── WeatherForecast.cs └── appsettings.json └── DotnetDocsShow.sln /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc 262 | /obj/ 263 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/Customers/Customer.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Extensions.Validation.Customers; 2 | 3 | public class Customer 4 | { 5 | public Guid Id { get; } = Guid.NewGuid(); 6 | 7 | public string FullName { get; init; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/Customers/CustomerEndpoints.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace DotnetDocsShow.Extensions.Validation.Customers; 4 | 5 | public static class CustomerEndpoints 6 | { 7 | public static void MapCustomerEndpoints(this WebApplication app) 8 | { 9 | app.MapGet("/customers", GetAllCustomers); 10 | app.MapGet("/customers/{id}", GetCustomerById); 11 | app.MapPost("/customers", CreateCustomer).WithValidator(); 12 | app.MapPut("/customers/{id}", UpdateCustomer); 13 | app.MapDelete("/customers/{id}", DeleteCustomerById); 14 | } 15 | 16 | public static void AddCustomerServices(this IServiceCollection services) 17 | { 18 | services.AddSingleton(); 19 | } 20 | 21 | internal static List GetAllCustomers(ICustomerService service) 22 | { 23 | return service.GetAll(); 24 | } 25 | 26 | internal static IResult GetCustomerById(ICustomerService service, Guid id) 27 | { 28 | var customer = service.GetById(id); 29 | return customer is not null ? Results.Ok(customer) : Results.NotFound(); 30 | } 31 | 32 | internal static async Task CreateCustomerWithValidation( 33 | ICustomerService service, Customer customer, 34 | IValidator validator) 35 | { 36 | var validate = await validator.ValidateAsync(customer); 37 | if (!validate.IsValid) 38 | { 39 | return Results.BadRequest(validate.Errors); 40 | } 41 | 42 | service.Create(customer); 43 | return Results.Created($"/customers/{customer.Id}", customer); 44 | } 45 | 46 | internal static IResult CreateCustomer( 47 | ICustomerService service, Customer customer) 48 | { 49 | service.Create(customer); 50 | return Results.Created($"/customers/{customer.Id}", customer); 51 | } 52 | 53 | internal static IResult UpdateCustomer(ICustomerService service, Guid id, Customer updatedCustomer) 54 | { 55 | var customer = service.GetById(id); 56 | if (customer is null) 57 | { 58 | return Results.NotFound(); 59 | } 60 | 61 | service.Update(updatedCustomer); 62 | return Results.Ok(updatedCustomer); 63 | } 64 | 65 | internal static IResult DeleteCustomerById(ICustomerService service, Guid id) 66 | { 67 | service.Delete(id); 68 | return Results.Ok(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/Customers/CustomerService.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Extensions.Validation.Customers; 2 | 3 | public class CustomerService : ICustomerService 4 | { 5 | private readonly Dictionary _customers = new(); 6 | 7 | public void Create(Customer? customer) 8 | { 9 | if (customer is null) 10 | { 11 | return; 12 | } 13 | 14 | _customers[customer.Id] = customer; 15 | } 16 | 17 | public Customer? GetById(Guid id) 18 | { 19 | return _customers.GetValueOrDefault(id); 20 | } 21 | 22 | public List GetAll() 23 | { 24 | return _customers.Values.ToList(); 25 | } 26 | 27 | public void Update(Customer customer) 28 | { 29 | var existingCustomer = GetById(customer.Id); 30 | if (existingCustomer is null) 31 | { 32 | return; 33 | } 34 | 35 | _customers[customer.Id] = customer; 36 | } 37 | 38 | public void Delete(Guid id) 39 | { 40 | _customers.Remove(id); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/Customers/CustomerValidation.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace DotnetDocsShow.Extensions.Validation.Customers; 4 | 5 | public class CustomerValidation : AbstractValidator 6 | { 7 | public CustomerValidation() 8 | { 9 | RuleFor(x => x.Id).NotEmpty(); 10 | RuleFor(x => x.FullName).NotEmpty(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/Customers/ICustomerService.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Extensions.Validation.Customers; 2 | 3 | public interface ICustomerService 4 | { 5 | void Create(Customer? customer); 6 | 7 | Customer? GetById(Guid id); 8 | 9 | List GetAll(); 10 | 11 | void Update(Customer customer); 12 | 13 | void Delete(Guid id); 14 | } 15 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/DotnetDocsShow.Extensions.Validation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/IAssemblyMarker.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Extensions.Validation; 2 | 3 | public interface IAssemblyMarker{} 4 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/Program.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Extensions.Validation; 2 | using DotnetDocsShow.Extensions.Validation.Customers; 3 | using FluentValidation; 4 | 5 | var builder = WebApplication.CreateBuilder(args); 6 | builder.Services.AddCustomerServices(); 7 | builder.Services.AddValidatorsFromAssemblyContaining(typeof(IAssemblyMarker)); 8 | 9 | var app = builder.Build(); 10 | app.MapCustomerEndpoints(); 11 | app.Run(); 12 | -------------------------------------------------------------------------------- /DotnetDocsShow.Extensions.Validation/ValidationExtensions.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace DotnetDocsShow.Extensions.Validation; 4 | 5 | public static class ValidationExtensions 6 | { 7 | public static RouteHandlerBuilder WithValidator( 8 | this RouteHandlerBuilder builder) where TType : class 9 | { 10 | builder.Add(endpointBuilder => 11 | { 12 | var originalRequestDelegate = endpointBuilder.RequestDelegate; 13 | endpointBuilder.RequestDelegate = async context => 14 | { 15 | var validator = context.RequestServices.GetService>(); 16 | 17 | if (validator is null) 18 | { 19 | await originalRequestDelegate!(context); 20 | return; 21 | } 22 | 23 | context.Request.EnableBuffering(); 24 | var model = await context.Request.ReadFromJsonAsync(); 25 | if (model is null) 26 | { 27 | context.Response.StatusCode = 400; 28 | await context.Response.WriteAsJsonAsync(new 29 | { 30 | error = "Couldn't map the model from the request body" 31 | }); 32 | return; 33 | } 34 | 35 | var result = await validator.ValidateAsync(model); 36 | if (!result.IsValid) 37 | { 38 | context.Response.StatusCode = 400; 39 | await context.Response.WriteAsJsonAsync(new { errors = result.Errors }); 40 | return; 41 | } 42 | 43 | context.Request.Body.Position = 0; 44 | await originalRequestDelegate!(context); 45 | }; 46 | }); 47 | return builder; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /DotnetDocsShow.Intro.MinimalApi/DotnetDocsShow.Intro.MinimalApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DotnetDocsShow.Intro.MinimalApi/Program.cs: -------------------------------------------------------------------------------- 1 | var app = WebApplication.Create(); 2 | 3 | app.MapGet("helloworld", () => "Hello world!"); 4 | 5 | app.Run(); 6 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/DotnetDocsShow.MinimalApiTests.Structured.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/EndpointDefinitionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.MinimalApiTests.Structured; 2 | 3 | public static class EndpointDefinitionExtensions 4 | { 5 | public static void AddEndpointDefinitions( 6 | this IServiceCollection services, params Type[] scanMarkers) 7 | { 8 | var endpointDefinitions = new List(); 9 | 10 | foreach (var marker in scanMarkers) 11 | { 12 | endpointDefinitions.AddRange( 13 | marker.Assembly.ExportedTypes 14 | .Where(x => typeof(IEndpointDefinition).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract) 15 | .Select(Activator.CreateInstance).Cast() 16 | ); 17 | } 18 | 19 | foreach (var endpointDefinition in endpointDefinitions) 20 | { 21 | endpointDefinition.DefineServices(services); 22 | } 23 | 24 | services.AddSingleton(endpointDefinitions as IReadOnlyCollection); 25 | } 26 | 27 | public static void UseEndpointDefinitions(this WebApplication app) 28 | { 29 | var definitions = app.Services.GetRequiredService>(); 30 | 31 | foreach (var endpointDefinition in definitions) 32 | { 33 | endpointDefinition.DefineEndpoints(app); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/EndpointDefinitions/CustomerEndpointDefinition.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.MinimalApiTests.Structured.Models; 2 | using DotnetDocsShow.MinimalApiTests.Structured.Services; 3 | 4 | namespace DotnetDocsShow.MinimalApiTests.Structured.EndpointDefinitions; 5 | 6 | public class CustomerEndpointDefinition : IEndpointDefinition 7 | { 8 | public void DefineEndpoints(WebApplication app) 9 | { 10 | app.MapGet("/customers", GetAllCustomers); 11 | app.MapGet("/customers/{id}", GetCustomerById); 12 | app.MapPost("/customers", CreateCustomer); 13 | app.MapPut("/customers/{id}", UpdateCustomer); 14 | app.MapDelete("/customers/{id}", DeleteCustomerById); 15 | } 16 | 17 | internal List GetAllCustomers(ICustomerService service) 18 | { 19 | return service.GetAll(); 20 | } 21 | 22 | internal IResult GetCustomerById(ICustomerService service, Guid id) 23 | { 24 | var customer = service.GetById(id); 25 | return customer is not null ? Results.Ok(customer) : Results.NotFound(); 26 | } 27 | 28 | internal IResult CreateCustomer(ICustomerService service, Customer customer) 29 | { 30 | service.Create(customer); 31 | return Results.Created($"/customers/{customer.Id}", customer); 32 | } 33 | 34 | internal IResult UpdateCustomer(ICustomerService service, Guid id, Customer updatedCustomer) 35 | { 36 | var customer = service.GetById(id); 37 | if (customer is null) 38 | { 39 | return Results.NotFound(); 40 | } 41 | 42 | service.Update(updatedCustomer); 43 | return Results.Ok(updatedCustomer); 44 | } 45 | 46 | internal IResult DeleteCustomerById(ICustomerService service, Guid id) 47 | { 48 | service.Delete(id); 49 | return Results.Ok(); 50 | } 51 | 52 | public void DefineServices(IServiceCollection services) 53 | { 54 | services.AddSingleton(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/EndpointDefinitions/SwaggerEndpointDefinition.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.OpenApi.Models; 2 | 3 | namespace DotnetDocsShow.MinimalApiTests.Structured.EndpointDefinitions; 4 | 5 | public class SwaggerEndpointDefinition : IEndpointDefinition 6 | { 7 | public void DefineEndpoints(WebApplication app) 8 | { 9 | app.UseSwagger(); 10 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "DotnetDocsShow.MinimalApiTests.Structured v1")); 11 | } 12 | 13 | public void DefineServices(IServiceCollection services) 14 | { 15 | services.AddEndpointsApiExplorer(); 16 | services.AddSwaggerGen(c => 17 | { 18 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "DotnetDocsShow.MinimalApiTests.Structured", Version = "v1" }); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/IEndpointDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.MinimalApiTests.Structured; 2 | 3 | public interface IEndpointDefinition 4 | { 5 | void DefineServices(IServiceCollection services); 6 | 7 | void DefineEndpoints(WebApplication app); 8 | } 9 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/Models/Customer.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace DotnetDocsShow.MinimalApiTests.Structured.Models; 4 | 5 | public class Customer 6 | { 7 | [JsonPropertyName("id")] 8 | public Guid Id { get; init; } = Guid.NewGuid(); 9 | 10 | [JsonPropertyName("fullName")] 11 | public string FullName { get; init; } = default!; 12 | } 13 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/Program.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.MinimalApiTests.Structured; 2 | 3 | var builder = WebApplication.CreateBuilder(args); 4 | builder.Services.AddEndpointDefinitions(typeof(IEndpointDefinition)); 5 | 6 | var app = builder.Build(); 7 | app.UseEndpointDefinitions(); 8 | 9 | app.Run(); 10 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/Services/CustomerService.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.MinimalApiTests.Structured.Models; 2 | 3 | namespace DotnetDocsShow.MinimalApiTests.Structured.Services; 4 | 5 | public class CustomerService : ICustomerService 6 | { 7 | private readonly Dictionary _customers = new(); 8 | 9 | public void Create(Customer? customer) 10 | { 11 | if (customer is null) 12 | { 13 | return; 14 | } 15 | 16 | _customers[customer.Id] = customer; 17 | } 18 | 19 | public Customer? GetById(Guid id) 20 | { 21 | return _customers.GetValueOrDefault(id); 22 | } 23 | 24 | public List GetAll() 25 | { 26 | return _customers.Values.ToList(); 27 | } 28 | 29 | public void Update(Customer customer) 30 | { 31 | var existingCustomer = GetById(customer.Id); 32 | if (existingCustomer is null) 33 | { 34 | return; 35 | } 36 | 37 | _customers[customer.Id] = customer; 38 | } 39 | 40 | public void Delete(Guid id) 41 | { 42 | _customers.Remove(id); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /DotnetDocsShow.MinimalApiTests.Structured/Services/ICustomerService.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.MinimalApiTests.Structured.Models; 2 | 3 | namespace DotnetDocsShow.MinimalApiTests.Structured.Services; 4 | 5 | public interface ICustomerService 6 | { 7 | void Create(Customer? customer); 8 | 9 | Customer? GetById(Guid id); 10 | 11 | List GetAll(); 12 | 13 | void Update(Customer customer); 14 | 15 | void Delete(Guid id); 16 | } 17 | -------------------------------------------------------------------------------- /DotnetDocsShow.NewWebApi/Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace DotnetDocsShow.NewWebApi.Controllers; 4 | 5 | [ApiController] 6 | [Route("[controller]")] 7 | public class WeatherForecastController : ControllerBase 8 | { 9 | private static readonly Random Random = new(489); 10 | private static readonly string[] Summaries = { 11 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 12 | }; 13 | 14 | [HttpGet(Name = "GetWeatherForecast")] 15 | public IEnumerable Get() 16 | { 17 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 18 | { 19 | Date = DateTime.Now.AddDays(index), 20 | TemperatureC = Random.Next(-20, 55), 21 | Summary = Summaries[Random.Next(Summaries.Length)] 22 | }) 23 | .ToArray(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /DotnetDocsShow.NewWebApi/DotnetDocsShow.NewWebApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /DotnetDocsShow.NewWebApi/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = WebApplication.CreateBuilder(args); 2 | 3 | // Add services to the container. 4 | 5 | builder.Services.AddControllers(); 6 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 7 | builder.Services.AddEndpointsApiExplorer(); 8 | builder.Services.AddSwaggerGen(); 9 | 10 | var app = builder.Build(); 11 | 12 | // Configure the HTTP request pipeline. 13 | if (app.Environment.IsDevelopment()) 14 | { 15 | app.UseSwagger(); 16 | app.UseSwaggerUI(); 17 | } 18 | 19 | app.UseHttpsRedirection(); 20 | 21 | app.UseAuthorization(); 22 | 23 | app.MapControllers(); 24 | 25 | app.Run(); -------------------------------------------------------------------------------- /DotnetDocsShow.NewWebApi/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:56176", 8 | "sslPort": 44384 9 | } 10 | }, 11 | "profiles": { 12 | "DotnetDocsShow.NewWebApi": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": false, 16 | "launchUrl": "swagger", 17 | "applicationUrl": "https://localhost:7256;http://localhost:5256", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | }, 22 | "IIS Express": { 23 | "commandName": "IISExpress", 24 | "launchBrowser": true, 25 | "launchUrl": "swagger", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DotnetDocsShow.NewWebApi/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.NewWebApi; 2 | 3 | public class WeatherForecast 4 | { 5 | public DateTime Date { get; set; } 6 | 7 | public int TemperatureC { get; set; } 8 | 9 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 10 | 11 | public string? Summary { get; set; } 12 | } -------------------------------------------------------------------------------- /DotnetDocsShow.NewWebApi/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /DotnetDocsShow.NewWebApi/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /DotnetDocsShow.OldWebApi/Controllers/WeatherForecastController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace DotnetDocsShow.OldWebApi.Controllers; 4 | 5 | [ApiController] 6 | [Route("[controller]")] 7 | public class WeatherForecastController : ControllerBase 8 | { 9 | private static readonly Random Random = new(489); 10 | private static readonly string[] Summaries = { 11 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 12 | }; 13 | 14 | [HttpGet] 15 | public IEnumerable Get() 16 | { 17 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 18 | { 19 | Date = DateTime.Now.AddDays(index), 20 | TemperatureC = Random.Next(-20, 55), 21 | Summary = Summaries[Random.Next(Summaries.Length)] 22 | }) 23 | .ToArray(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /DotnetDocsShow.OldWebApi/DotnetDocsShow.OldWebApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /DotnetDocsShow.OldWebApi/Program.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.OldWebApi; 2 | 3 | public class Program 4 | { 5 | public static void Main(string[] args) 6 | { 7 | CreateHostBuilder(args).Build().Run(); 8 | } 9 | 10 | public static IHostBuilder CreateHostBuilder(string[] args) => 11 | Host.CreateDefaultBuilder(args) 12 | .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); 13 | } -------------------------------------------------------------------------------- /DotnetDocsShow.OldWebApi/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:17516", 8 | "sslPort": 44325 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "swagger", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "DotnetDocsShow.OldWebApi": { 21 | "commandName": "Project", 22 | "dotnetRunMessages": "true", 23 | "launchBrowser": false, 24 | "launchUrl": "swagger", 25 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DotnetDocsShow.OldWebApi/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.OpenApi.Models; 2 | 3 | namespace DotnetDocsShow.OldWebApi; 4 | 5 | public class Startup 6 | { 7 | public Startup(IConfiguration configuration) 8 | { 9 | Configuration = configuration; 10 | } 11 | 12 | public IConfiguration Configuration { get; } 13 | 14 | // This method gets called by the runtime. Use this method to add services to the container. 15 | public void ConfigureServices(IServiceCollection services) 16 | { 17 | services.AddControllers(); 18 | services.AddSwaggerGen(c => 19 | { 20 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "DotnetDocsShow.OldWebApi", Version = "v1" }); 21 | }); 22 | } 23 | 24 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 25 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 26 | { 27 | if (env.IsDevelopment()) 28 | { 29 | app.UseDeveloperExceptionPage(); 30 | app.UseSwagger(); 31 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "DotnetDocsShow.OldWebApi v1")); 32 | } 33 | 34 | app.UseHttpsRedirection(); 35 | 36 | app.UseRouting(); 37 | 38 | app.UseAuthorization(); 39 | 40 | app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); 41 | } 42 | } -------------------------------------------------------------------------------- /DotnetDocsShow.OldWebApi/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.OldWebApi; 2 | 3 | public class WeatherForecast 4 | { 5 | public DateTime Date { get; set; } 6 | 7 | public int TemperatureC { get; set; } 8 | 9 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 10 | 11 | public string Summary { get; set; } 12 | } -------------------------------------------------------------------------------- /DotnetDocsShow.OldWebApi/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DotnetDocsShow.OldWebApi/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /DotnetDocsShow.PerformanceTests/DotnetDocsShow.PerformanceTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DotnetDocsShow.PerformanceTests/Program.cs: -------------------------------------------------------------------------------- 1 | using NBomber.Contracts; 2 | using NBomber.CSharp; 3 | using NBomber.Plugins.Http.CSharp; 4 | 5 | var httpFactory = HttpClientFactory.Create(); 6 | 7 | var oldWebApiStep = CreateStep("old_web_api_step", httpFactory, "https://localhost:5001/weatherforecast"); 8 | var newWebApiStep = CreateStep("new_web_api_step", httpFactory, "https://localhost:7256/weatherforecast"); 9 | var minimalApiStep = CreateStep("minimal_api_step", httpFactory, "https://localhost:1337/weatherforecast"); 10 | 11 | var oldWebApiScenario = CreateScenario("old_web_api", oldWebApiStep, 10, TimeSpan.FromSeconds(60)); 12 | var newWebApiScenario = CreateScenario("new_web_api", newWebApiStep, 10, TimeSpan.FromSeconds(60)); 13 | var minimalApiScenario = CreateScenario("minimal_api", minimalApiStep, 10, TimeSpan.FromSeconds(60)); 14 | 15 | NBomberRunner 16 | .RegisterScenarios(oldWebApiScenario, newWebApiScenario, minimalApiScenario) 17 | .Run(); 18 | 19 | IStep CreateStep(string stepName, IClientFactory httpClientFactory, string endpoint) => 20 | Step.Create(stepName, httpClientFactory, async context => 21 | { 22 | var response = await context.Client.GetAsync(endpoint, context.CancellationToken); 23 | 24 | return response.IsSuccessStatusCode 25 | ? Response.Ok(statusCode: (int)response.StatusCode) 26 | : Response.Fail(statusCode: (int)response.StatusCode); 27 | }); 28 | 29 | Scenario CreateScenario(string scenarioName, IStep step, int copies, TimeSpan duration) => 30 | ScenarioBuilder 31 | .CreateScenario(scenarioName, step) 32 | .WithWarmUpDuration(TimeSpan.FromSeconds(5)) 33 | .WithLoadSimulations(Simulation.KeepConstant(copies, duration)); 34 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Extensions/Customers/Customer.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Extensions.Customers; 2 | 3 | public class Customer 4 | { 5 | public Guid Id { get; } = Guid.NewGuid(); 6 | 7 | public string FullName { get; init; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Extensions/Customers/CustomerEndpoints.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Extensions.Customers; 2 | 3 | public static class CustomerEndpoints 4 | { 5 | public static void MapCustomerEndpoints(this WebApplication app) 6 | { 7 | app.MapGet("/customers", GetAllCustomers); 8 | app.MapGet("/customers/{id}", GetCustomerById); 9 | app.MapPost("/customers", CreateCustomer); 10 | app.MapPut("/customers/{id}", UpdateCustomer); 11 | app.MapDelete("/customers/{id}", DeleteCustomerById); 12 | } 13 | 14 | public static void AddCustomerServices(this IServiceCollection services) 15 | { 16 | services.AddSingleton(); 17 | } 18 | 19 | internal static List GetAllCustomers(ICustomerService service) 20 | { 21 | return service.GetAll(); 22 | } 23 | 24 | internal static IResult GetCustomerById(ICustomerService service, Guid id) 25 | { 26 | var customer = service.GetById(id); 27 | return customer is not null ? Results.Ok(customer) : Results.NotFound(); 28 | } 29 | 30 | internal static IResult CreateCustomer(ICustomerService service, Customer customer) 31 | { 32 | service.Create(customer); 33 | return Results.Created($"/customers/{customer.Id}", customer); 34 | } 35 | 36 | internal static IResult UpdateCustomer(ICustomerService service, Guid id, Customer updatedCustomer) 37 | { 38 | var customer = service.GetById(id); 39 | if (customer is null) 40 | { 41 | return Results.NotFound(); 42 | } 43 | 44 | service.Update(updatedCustomer); 45 | return Results.Ok(updatedCustomer); 46 | } 47 | 48 | internal static IResult DeleteCustomerById(ICustomerService service, Guid id) 49 | { 50 | service.Delete(id); 51 | return Results.Ok(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Extensions/Customers/CustomerService.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Extensions.Customers; 2 | 3 | public class CustomerService : ICustomerService 4 | { 5 | private readonly Dictionary _customers = new(); 6 | 7 | public void Create(Customer? customer) 8 | { 9 | if (customer is null) 10 | { 11 | return; 12 | } 13 | 14 | _customers[customer.Id] = customer; 15 | } 16 | 17 | public Customer? GetById(Guid id) 18 | { 19 | return _customers.GetValueOrDefault(id); 20 | } 21 | 22 | public List GetAll() 23 | { 24 | return _customers.Values.ToList(); 25 | } 26 | 27 | public void Update(Customer customer) 28 | { 29 | var existingCustomer = GetById(customer.Id); 30 | if (existingCustomer is null) 31 | { 32 | return; 33 | } 34 | 35 | _customers[customer.Id] = customer; 36 | } 37 | 38 | public void Delete(Guid id) 39 | { 40 | _customers.Remove(id); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Extensions/Customers/ICustomerService.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Extensions.Customers; 2 | 3 | public interface ICustomerService 4 | { 5 | void Create(Customer? customer); 6 | 7 | Customer? GetById(Guid id); 8 | 9 | List GetAll(); 10 | 11 | void Update(Customer customer); 12 | 13 | void Delete(Guid id); 14 | } 15 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Extensions/DotnetDocsShow.Structured.Extensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Extensions/Program.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Extensions.Customers; 2 | 3 | var builder = WebApplication.CreateBuilder(args); 4 | 5 | builder.Services.AddCustomerServices(); 6 | 7 | var app = builder.Build(); 8 | 9 | app.MapCustomerEndpoints(); 10 | 11 | app.Run(); 12 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/DotnetDocsShow.Structured.Mediator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/Handlers/CreateCustomerRequestHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using DotnetDocsShow.Structured.Mediator.Models; 3 | using DotnetDocsShow.Structured.Mediator.Services; 4 | using MediatR; 5 | 6 | namespace DotnetDocsShow.Structured.Mediator.Handlers; 7 | 8 | public record CreateCustomerRequest : IRequest 9 | { 10 | [JsonPropertyName("id")] 11 | public Guid Id { get; init; } = Guid.NewGuid(); 12 | 13 | [JsonPropertyName("fullName")] 14 | public string FullName { get; init; } = default!; 15 | } 16 | 17 | public class CreateCustomerRequestHandler 18 | : IRequestHandler 19 | { 20 | private readonly ICustomerService _customerService; 21 | 22 | public CreateCustomerRequestHandler(ICustomerService customerService) 23 | { 24 | _customerService = customerService; 25 | } 26 | 27 | public Task Handle(CreateCustomerRequest request, CancellationToken cancellationToken) 28 | { 29 | var customer = new Customer 30 | { 31 | FullName = request.FullName, 32 | Id = request.Id 33 | }; 34 | _customerService.Create(customer); 35 | var response = Results.Created($"/customers/{customer.Id}", customer); 36 | return Task.FromResult(response); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/Handlers/DeleteCustomerByIdRequestHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using DotnetDocsShow.Structured.Mediator.Services; 3 | using MediatR; 4 | 5 | namespace DotnetDocsShow.Structured.Mediator.Handlers; 6 | 7 | public record DeleteCustomerByIdRequest : IRequest 8 | { 9 | [JsonPropertyName("id")] 10 | public Guid Id { get; init; } 11 | 12 | public DeleteCustomerByIdRequest(Guid id) 13 | { 14 | Id = id; 15 | } 16 | } 17 | 18 | public class DeleteCustomerByIdRequestHandler 19 | : IRequestHandler 20 | { 21 | private readonly ICustomerService _customerService; 22 | 23 | public DeleteCustomerByIdRequestHandler(ICustomerService customerService) 24 | { 25 | _customerService = customerService; 26 | } 27 | 28 | public Task Handle(DeleteCustomerByIdRequest request, CancellationToken cancellationToken) 29 | { 30 | _customerService.Delete(request.Id); 31 | return Task.FromResult(Results.Ok()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/Handlers/GetAllCustomersRequestHandler.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Mediator.Services; 2 | using MediatR; 3 | 4 | namespace DotnetDocsShow.Structured.Mediator.Handlers; 5 | 6 | public record GetAllCustomersRequest : IRequest; 7 | 8 | public class GetAllCustomersRequestHandler 9 | : IRequestHandler 10 | { 11 | private readonly ICustomerService _customerService; 12 | 13 | public GetAllCustomersRequestHandler(ICustomerService customerService) 14 | { 15 | _customerService = customerService; 16 | } 17 | 18 | public Task Handle( 19 | GetAllCustomersRequest request, CancellationToken cancellationToken) 20 | { 21 | var customers = _customerService.GetAll(); 22 | var response = Results.Ok(customers); 23 | return Task.FromResult(response); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/Handlers/GetCustomerByIdRequestHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | using DotnetDocsShow.Structured.Mediator.Services; 3 | using MediatR; 4 | 5 | namespace DotnetDocsShow.Structured.Mediator.Handlers; 6 | 7 | public record GetCustomerByIdRequest : IRequest 8 | { 9 | [JsonPropertyName("id")] 10 | public Guid Id { get; init; } 11 | 12 | public GetCustomerByIdRequest(Guid id) 13 | { 14 | Id = id; 15 | } 16 | } 17 | 18 | public class GetCustomerByIdRequestHandler 19 | : IRequestHandler 20 | { 21 | private readonly ICustomerService _customerService; 22 | 23 | public GetCustomerByIdRequestHandler(ICustomerService customerService) 24 | { 25 | _customerService = customerService; 26 | } 27 | 28 | public Task Handle(GetCustomerByIdRequest request, CancellationToken cancellationToken) 29 | { 30 | var customer = _customerService.GetById(request.Id); 31 | var response = customer is not null ? Results.Ok(customer) : Results.NotFound(); 32 | return Task.FromResult(response); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/Models/Customer.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Mediator.Models; 2 | 3 | public class Customer 4 | { 5 | public Guid Id { get; init; } = Guid.NewGuid(); 6 | 7 | public string FullName { get; init; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/Program.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Mediator; 2 | using DotnetDocsShow.Structured.Mediator.Handlers; 3 | using DotnetDocsShow.Structured.Mediator.Models; 4 | using DotnetDocsShow.Structured.Mediator.Services; 5 | using MediatR; 6 | 7 | var builder = WebApplication.CreateBuilder(); 8 | 9 | builder.Services.AddSingleton(); 10 | builder.Services.AddMediatR(typeof(Customer)); 11 | 12 | var app = builder.Build(); 13 | 14 | app.MapGet("customers", async (IMediator mediator) => await mediator.Send(new GetAllCustomersRequest())); 15 | app.MapGet("/customers/{id}", async (IMediator mediator, Guid id) => await mediator.Send(new GetCustomerByIdRequest(id))); 16 | app.MapPost("/customers", async (IMediator mediator, CreateCustomerRequest request) => await mediator.Send(request)); 17 | app.MapDelete("/customers/{id}", async (IMediator mediator, Guid id) => await mediator.Send(new DeleteCustomerByIdRequest(id))); 18 | 19 | app.Run(); 20 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/Services/CustomerService.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Mediator.Models; 2 | 3 | namespace DotnetDocsShow.Structured.Mediator.Services; 4 | 5 | public class CustomerService : ICustomerService 6 | { 7 | private readonly Dictionary _customers = new(); 8 | 9 | public void Create(Customer? customer) 10 | { 11 | if (customer is null) 12 | { 13 | return; 14 | } 15 | 16 | _customers[customer.Id] = customer; 17 | } 18 | 19 | public Customer? GetById(Guid id) 20 | { 21 | return _customers.GetValueOrDefault(id); 22 | } 23 | 24 | public List GetAll() 25 | { 26 | return _customers.Values.ToList(); 27 | } 28 | 29 | public void Update(Customer customer) 30 | { 31 | var existingCustomer = GetById(customer.Id); 32 | if (existingCustomer is null) 33 | { 34 | return; 35 | } 36 | 37 | _customers[customer.Id] = customer; 38 | } 39 | 40 | public void Delete(Guid id) 41 | { 42 | _customers.Remove(id); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Mediator/Services/ICustomerService.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Mediator.Models; 2 | 3 | namespace DotnetDocsShow.Structured.Mediator.Services; 4 | 5 | public interface ICustomerService 6 | { 7 | void Create(Customer? customer); 8 | 9 | Customer? GetById(Guid id); 10 | 11 | List GetAll(); 12 | 13 | void Update(Customer customer); 14 | 15 | void Delete(Guid id); 16 | } 17 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/DotnetDocsShow.Structured.Scanning.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/EndpointDefinitionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Scanning; 2 | 3 | public static class EndpointDefinitionExtensions 4 | { 5 | public static void AddEndpointDefinitions( 6 | this IServiceCollection services, params Type[] scanMarkers) 7 | { 8 | var endpointDefinitions = new List(); 9 | 10 | foreach (var marker in scanMarkers) 11 | { 12 | endpointDefinitions.AddRange( 13 | marker.Assembly.ExportedTypes 14 | .Where(x => typeof(IEndpointDefinition).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract) 15 | .Select(Activator.CreateInstance).Cast() 16 | ); 17 | } 18 | 19 | foreach (var endpointDefinition in endpointDefinitions) 20 | { 21 | endpointDefinition.DefineServices(services); 22 | } 23 | 24 | services.AddSingleton(endpointDefinitions as IReadOnlyCollection); 25 | } 26 | 27 | public static void UseEndpointDefinitions(this WebApplication app) 28 | { 29 | var definitions = app.Services.GetRequiredService>(); 30 | 31 | foreach (var endpointDefinition in definitions) 32 | { 33 | endpointDefinition.DefineEndpoints(app); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/EndpointDefinitions/CustomerEndpointDefinition.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Scanning.Models; 2 | using DotnetDocsShow.Structured.Scanning.Services; 3 | 4 | namespace DotnetDocsShow.Structured.Scanning.EndpointDefinitions; 5 | 6 | public class CustomerEndpointDefinition : IEndpointDefinition 7 | { 8 | public void DefineEndpoints(WebApplication app) 9 | { 10 | app.MapGet("/customers", GetAllCustomers); 11 | app.MapGet("/customers/{id}", GetCustomerById); 12 | app.MapPost("/customers", CreateCustomer); 13 | app.MapPut("/customers/{id}", UpdateCustomer); 14 | app.MapDelete("/customers/{id}", DeleteCustomerById); 15 | } 16 | 17 | internal List GetAllCustomers(ICustomerService service) 18 | { 19 | return service.GetAll(); 20 | } 21 | 22 | internal IResult GetCustomerById(ICustomerService service, Guid id) 23 | { 24 | var customer = service.GetById(id); 25 | return customer is not null ? Results.Ok(customer) : Results.NotFound(); 26 | } 27 | 28 | internal IResult CreateCustomer(ICustomerService service, Customer customer) 29 | { 30 | service.Create(customer); 31 | return Results.Created($"/customers/{customer.Id}", customer); 32 | } 33 | 34 | internal IResult UpdateCustomer(ICustomerService service, Guid id, Customer updatedCustomer) 35 | { 36 | var customer = service.GetById(id); 37 | if (customer is null) 38 | { 39 | return Results.NotFound(); 40 | } 41 | 42 | service.Update(updatedCustomer); 43 | return Results.Ok(updatedCustomer); 44 | } 45 | 46 | internal IResult DeleteCustomerById(ICustomerService service, Guid id) 47 | { 48 | service.Delete(id); 49 | return Results.Ok(); 50 | } 51 | 52 | public void DefineServices(IServiceCollection services) 53 | { 54 | services.AddSingleton(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/EndpointDefinitions/PaymentsEndpointDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Scanning.EndpointDefinitions; 2 | 3 | public class PaymentsEndpointDefinition : IEndpointDefinition 4 | { 5 | public void DefineServices(IServiceCollection services) 6 | { 7 | 8 | } 9 | 10 | public void DefineEndpoints(WebApplication app) 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/EndpointDefinitions/SwaggerEndpointDefinition.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.OpenApi.Models; 2 | 3 | namespace DotnetDocsShow.Structured.Scanning.EndpointDefinitions; 4 | 5 | public class SwaggerEndpointDefinition : IEndpointDefinition 6 | { 7 | public void DefineEndpoints(WebApplication app) 8 | { 9 | app.UseSwagger(); 10 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "DotnetDocsShow.Structured.Custom v1")); 11 | } 12 | 13 | public void DefineServices(IServiceCollection services) 14 | { 15 | services.AddEndpointsApiExplorer(); 16 | services.AddSwaggerGen(c => 17 | { 18 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "DotnetDocsShow.Structured.Custom", Version = "v1" }); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/IEndpointDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Scanning; 2 | 3 | public interface IEndpointDefinition 4 | { 5 | void DefineServices(IServiceCollection services); 6 | 7 | void DefineEndpoints(WebApplication app); 8 | } 9 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/Models/Customer.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Structured.Scanning.Models; 2 | 3 | public class Customer 4 | { 5 | public Guid Id { get; init; } = Guid.NewGuid(); 6 | 7 | public string FullName { get; init; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/Program.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Scanning; 2 | 3 | var builder = WebApplication.CreateBuilder(args); 4 | builder.Services.AddEndpointDefinitions(typeof(IEndpointDefinition)); 5 | 6 | var app = builder.Build(); 7 | app.UseEndpointDefinitions(); 8 | 9 | app.Run(); 10 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/Services/CustomerService.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Scanning.Models; 2 | 3 | namespace DotnetDocsShow.Structured.Scanning.Services; 4 | 5 | public class CustomerService : ICustomerService 6 | { 7 | private readonly Dictionary _customers = new(); 8 | 9 | public void Create(Customer? customer) 10 | { 11 | if (customer is null) 12 | { 13 | return; 14 | } 15 | 16 | _customers[customer.Id] = customer; 17 | } 18 | 19 | public Customer? GetById(Guid id) 20 | { 21 | return _customers.GetValueOrDefault(id); 22 | } 23 | 24 | public List GetAll() 25 | { 26 | return _customers.Values.ToList(); 27 | } 28 | 29 | public void Update(Customer customer) 30 | { 31 | var existingCustomer = GetById(customer.Id); 32 | if (existingCustomer is null) 33 | { 34 | return; 35 | } 36 | 37 | _customers[customer.Id] = customer; 38 | } 39 | 40 | public void Delete(Guid id) 41 | { 42 | _customers.Remove(id); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /DotnetDocsShow.Structured.Scanning/Services/ICustomerService.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Structured.Scanning.Models; 2 | 3 | namespace DotnetDocsShow.Structured.Scanning.Services; 4 | 5 | public interface ICustomerService 6 | { 7 | void Create(Customer? customer); 8 | 9 | Customer? GetById(Guid id); 10 | 11 | List GetAll(); 12 | 13 | void Update(Customer customer); 14 | 15 | void Delete(Guid id); 16 | } 17 | -------------------------------------------------------------------------------- /DotnetDocsShow.Tests.Integration/BroadCustomerEndpointsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Http.Json; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | using DotnetDocsShow.MinimalApiTests.Structured.Models; 7 | using FluentAssertions; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using NSubstitute; 10 | using Xunit; 11 | 12 | namespace DotnetDocsShow.Tests.Integration; 13 | 14 | public class BroadCustomerEndpointsTests 15 | { 16 | [Fact] 17 | public async Task GetCustomerById_ReturnCustomer_WhenCustomerExists() 18 | { 19 | //Arrange 20 | var id = Guid.NewGuid(); 21 | var customer = new Customer{ Id = id, FullName = "Nick Chapsas"}; 22 | 23 | using var app = new TestApplicationFactory(); 24 | 25 | var httpClient = app.CreateClient(); 26 | await httpClient.PostAsJsonAsync("/customers", customer); 27 | 28 | //Act 29 | var response = await httpClient.GetAsync($"/customers/{id}"); 30 | var responseText = await response.Content.ReadAsStringAsync(); 31 | var customerResult = JsonSerializer.Deserialize(responseText); 32 | 33 | //Assert 34 | response.StatusCode.Should().Be(HttpStatusCode.OK); 35 | customerResult.Should().BeEquivalentTo(customer); 36 | } 37 | 38 | [Fact] 39 | public async Task GetCustomerById_ReturnNotFound_WhenCustomerDoesNotExists() 40 | { 41 | //Arrange 42 | using var app = new TestApplicationFactory(); 43 | 44 | var guid = Guid.NewGuid(); 45 | var httpClient = app.CreateClient(); 46 | 47 | //Act 48 | var response = await httpClient.GetAsync($"/customers/{guid}"); 49 | 50 | //Assert 51 | response.StatusCode.Should().Be(HttpStatusCode.NotFound); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DotnetDocsShow.Tests.Integration/DotnetDocsShow.Tests.Integration.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | all 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /DotnetDocsShow.Tests.Integration/NarrowCustomerEndpointsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Text.Json; 4 | using System.Threading.Tasks; 5 | using DotnetDocsShow.MinimalApiTests.Structured.Models; 6 | using DotnetDocsShow.MinimalApiTests.Structured.Services; 7 | using FluentAssertions; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using NSubstitute; 10 | using Xunit; 11 | 12 | namespace DotnetDocsShow.Tests.Integration; 13 | 14 | public class NarrowCustomerEndpointsTests 15 | { 16 | private readonly ICustomerService _customerService = 17 | Substitute.For(); 18 | 19 | [Fact] 20 | public async Task GetCustomerById_ReturnCustomer_WhenCustomerExists() 21 | { 22 | //Arrange 23 | var id = Guid.NewGuid(); 24 | var customer = new Customer{ Id = id, FullName = "Nick Chapsas"}; 25 | _customerService.GetById(Arg.Is(id)).Returns(customer); 26 | 27 | using var app = new TestApplicationFactory(x => 28 | { 29 | x.AddSingleton(_customerService); 30 | }); 31 | 32 | var httpClient = app.CreateClient(); 33 | 34 | //Act 35 | var response = await httpClient.GetAsync($"/customers/{id}"); 36 | var responseText = await response.Content.ReadAsStringAsync(); 37 | var customerResult = JsonSerializer.Deserialize(responseText); 38 | 39 | //Assert 40 | response.StatusCode.Should().Be(HttpStatusCode.OK); 41 | customerResult.Should().BeEquivalentTo(customer); 42 | } 43 | 44 | [Fact] 45 | public async Task GetCustomerById_ReturnNotFound_WhenCustomerDoesNotExists() 46 | { 47 | //Arrange 48 | _customerService.GetById(Arg.Any()).Returns((Customer?)null); 49 | 50 | using var app = new TestApplicationFactory(x => 51 | { 52 | x.AddSingleton(_customerService); 53 | }); 54 | 55 | var guid = Guid.NewGuid(); 56 | var httpClient = app.CreateClient(); 57 | 58 | //Act 59 | var response = await httpClient.GetAsync($"/customers/{guid}"); 60 | 61 | //Assert 62 | response.StatusCode.Should().Be(HttpStatusCode.NotFound); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /DotnetDocsShow.Tests.Integration/TestApplicationFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Mvc.Testing; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Hosting; 5 | 6 | namespace DotnetDocsShow.Tests.Integration; 7 | 8 | internal class TestApplicationFactory : WebApplicationFactory 9 | { 10 | private readonly Action? _serviceOverride; 11 | 12 | public TestApplicationFactory(Action? serviceOverride = null) 13 | { 14 | _serviceOverride = serviceOverride; 15 | } 16 | 17 | protected override IHost CreateHost(IHostBuilder builder) 18 | { 19 | if (_serviceOverride is not null) 20 | { 21 | builder.ConfigureServices(_serviceOverride); 22 | } 23 | 24 | return base.CreateHost(builder); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /DotnetDocsShow.Tests.Unit/CustomerEndpointDefinitionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using DotnetDocsShow.MinimalApiTests.Structured.EndpointDefinitions; 5 | using DotnetDocsShow.MinimalApiTests.Structured.Models; 6 | using DotnetDocsShow.MinimalApiTests.Structured.Services; 7 | using FluentAssertions; 8 | using NSubstitute; 9 | using Xunit; 10 | 11 | namespace DotnetDocsShow.Tests.Unit; 12 | 13 | public class CustomerEndpointDefinitionTests 14 | { 15 | private readonly ICustomerService _customerService = 16 | Substitute.For(); 17 | 18 | private readonly CustomerEndpointDefinition _sut = new(); 19 | 20 | [Fact] 21 | public void GetAllCustomers_ReturnEmptyList_WhenNoCustomersExist() 22 | { 23 | //Arrange 24 | _customerService.GetAll().Returns(new List()); 25 | 26 | //Act 27 | var result = _sut.GetAllCustomers(_customerService); 28 | 29 | //Assert 30 | result.Should().BeEmpty(); 31 | } 32 | 33 | [Fact] 34 | public void GetAllCustomers_ReturnsCustomer_WhenCustomerExists() 35 | { 36 | //Arrange 37 | var id = Guid.NewGuid(); 38 | var customer = new Customer { Id = id, FullName = "Nick Chapsas" }; 39 | _customerService.GetAll().Returns(new List { customer }); 40 | 41 | //Act 42 | var result = _sut.GetAllCustomers(_customerService); 43 | 44 | //Assert 45 | result.Should().ContainSingle(x => x.Id == id && x.FullName == "Nick Chapsas"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /DotnetDocsShow.Tests.Unit/DotnetDocsShow.Tests.Unit.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | runtime; build; native; contentfiles; analyzers; buildtransitive 17 | all 18 | 19 | 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | all 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /DotnetDocsShow.Tests.Unit/ResultExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Http; 3 | 4 | namespace DotnetDocsShow.Tests.Unit; 5 | 6 | public static class ResultExtensions 7 | { 8 | public static T? GetOkObjectResultValue(this IResult result) 9 | { 10 | return (T?)Type.GetType("Microsoft.AspNetCore.Http.Result.OkObjectResult, Microsoft.AspNetCore.Http.Results")? 11 | .GetProperty("Value", 12 | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public)? 13 | .GetValue(result); 14 | } 15 | 16 | public static int? GetOkObjectResultStatusCode(this IResult result) 17 | { 18 | return (int?)Type.GetType("Microsoft.AspNetCore.Http.Result.OkObjectResult, Microsoft.AspNetCore.Http.Results")? 19 | .GetProperty("StatusCode", 20 | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public)? 21 | .GetValue(result); 22 | } 23 | 24 | public static int? GetNotFoundResultStatusCode(this IResult result) 25 | { 26 | return (int?)Type.GetType("Microsoft.AspNetCore.Http.Result.NotFoundObjectResult, Microsoft.AspNetCore.Http.Results")? 27 | .GetProperty("StatusCode", 28 | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public)? 29 | .GetValue(result); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DotnetDocsShow.Weather.MinimalApi/DotnetDocsShow.Weather.MinimalApi.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /DotnetDocsShow.Weather.MinimalApi/Program.cs: -------------------------------------------------------------------------------- 1 | using DotnetDocsShow.Weather.MinimalApi; 2 | 3 | var builder = WebApplication.CreateBuilder(args); 4 | 5 | // Add services to the container. 6 | // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle 7 | builder.Services.AddEndpointsApiExplorer(); 8 | builder.Services.AddSwaggerGen(); 9 | builder.Services.AddAuthorization(); 10 | 11 | var app = builder.Build(); 12 | 13 | // Configure the HTTP request pipeline. 14 | if (app.Environment.IsDevelopment()) 15 | { 16 | app.UseSwagger(); 17 | app.UseSwaggerUI(); 18 | } 19 | 20 | app.UseHttpsRedirection(); 21 | 22 | app.UseAuthorization(); 23 | 24 | app.MapWeatherEndpoints(); 25 | 26 | app.Run("https://localhost:1337"); 27 | -------------------------------------------------------------------------------- /DotnetDocsShow.Weather.MinimalApi/WeatherEndpoints.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Weather.MinimalApi; 2 | 3 | public static class WeatherEndpoints 4 | { 5 | private static Random Random = new(489); 6 | private static string[] Summaries = { 7 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 8 | }; 9 | 10 | public static void MapWeatherEndpoints(this WebApplication app) 11 | { 12 | app.MapGet("weatherforecast", () => 13 | { 14 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast 15 | { 16 | Date = DateTime.Now.AddDays(index), 17 | TemperatureC = Random.Next(-20, 55), 18 | Summary = Summaries[Random.Next(Summaries.Length)] 19 | }) 20 | .ToArray(); 21 | }) 22 | .Produces(200, typeof(IEnumerable)) 23 | .AllowAnonymous(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /DotnetDocsShow.Weather.MinimalApi/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | namespace DotnetDocsShow.Weather.MinimalApi; 2 | 3 | public class WeatherForecast 4 | { 5 | public DateTime Date { get; set; } 6 | 7 | public int TemperatureC { get; set; } 8 | 9 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 10 | 11 | public string? Summary { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /DotnetDocsShow.Weather.MinimalApi/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /DotnetDocsShow.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1. Comparision", "1. Comparision", "{6FB66046-57C1-4669-84E1-0905DADC000E}" 4 | EndProject 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4. Structuring", "4. Structuring", "{8618805B-A0E5-4B0A-B52D-FF5429D814E2}" 6 | EndProject 7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "5. Testing", "5. Testing", "{1E5E6DC2-39AE-4B52-83A7-46B28FEF72C3}" 8 | EndProject 9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2. Performance", "2. Performance", "{A18A5368-4F83-428C-ABA5-838FE467A581}" 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.NewWebApi", "DotnetDocsShow.NewWebApi\DotnetDocsShow.NewWebApi.csproj", "{6CA5CC96-0678-4723-B5B3-E2464516C277}" 12 | EndProject 13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.PerformanceTests", "DotnetDocsShow.PerformanceTests\DotnetDocsShow.PerformanceTests.csproj", "{71788840-6B85-42A5-9D52-D51A802A21BE}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.OldWebApi", "DotnetDocsShow.OldWebApi\DotnetDocsShow.OldWebApi.csproj", "{5EB40414-02BE-44A5-A14C-E619914A0F4A}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.Weather.MinimalApi", "DotnetDocsShow.Weather.MinimalApi\DotnetDocsShow.Weather.MinimalApi.csproj", "{AD793B6C-DF05-458E-854B-ECFCAF7167AD}" 18 | EndProject 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.Tests.Unit", "DotnetDocsShow.Tests.Unit\DotnetDocsShow.Tests.Unit.csproj", "{96598D5F-199D-45E7-9F80-98FD10DCD24A}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.Tests.Integration", "DotnetDocsShow.Tests.Integration\DotnetDocsShow.Tests.Integration.csproj", "{0D8831BD-6C91-49ED-9BE7-AEA7A6DA821F}" 22 | EndProject 23 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.MinimalApiTests.Structured", "DotnetDocsShow.MinimalApiTests.Structured\DotnetDocsShow.MinimalApiTests.Structured.csproj", "{E6AFFD49-C560-4947-8076-48E3F87AACAC}" 24 | EndProject 25 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.Structured.Scanning", "DotnetDocsShow.Structured.Scanning\DotnetDocsShow.Structured.Scanning.csproj", "{D7F4582E-2A51-4BCA-A4D6-A11B92EDAA2F}" 26 | EndProject 27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.Structured.Extensions", "DotnetDocsShow.Structured.Extensions\DotnetDocsShow.Structured.Extensions.csproj", "{020FC895-5E41-41A6-9C10-E2BCEBE40842}" 28 | EndProject 29 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.Structured.Mediator", "DotnetDocsShow.Structured.Mediator\DotnetDocsShow.Structured.Mediator.csproj", "{DCFF64BC-6B91-4121-BB4B-0A34AD3A6C84}" 30 | EndProject 31 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0. Intro", "0. Intro", "{8975828E-1794-41B6-8F82-41F70F52C270}" 32 | EndProject 33 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3. Extensions", "3. Extensions", "{6BD6DACA-80E0-4683-A6B3-649D79F8994C}" 34 | EndProject 35 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.Extensions.Validation", "DotnetDocsShow.Extensions.Validation\DotnetDocsShow.Extensions.Validation.csproj", "{12E1D11E-6E0E-4F40-91BB-996E71CC15C3}" 36 | EndProject 37 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotnetDocsShow.Intro.MinimalApi", "DotnetDocsShow.Intro.MinimalApi\DotnetDocsShow.Intro.MinimalApi.csproj", "{A3ECA132-FE31-46DF-8715-285B41409A1D}" 38 | EndProject 39 | Global 40 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 41 | Debug|Any CPU = Debug|Any CPU 42 | Release|Any CPU = Release|Any CPU 43 | EndGlobalSection 44 | GlobalSection(NestedProjects) = preSolution 45 | {6CA5CC96-0678-4723-B5B3-E2464516C277} = {6FB66046-57C1-4669-84E1-0905DADC000E} 46 | {71788840-6B85-42A5-9D52-D51A802A21BE} = {A18A5368-4F83-428C-ABA5-838FE467A581} 47 | {5EB40414-02BE-44A5-A14C-E619914A0F4A} = {6FB66046-57C1-4669-84E1-0905DADC000E} 48 | {AD793B6C-DF05-458E-854B-ECFCAF7167AD} = {6FB66046-57C1-4669-84E1-0905DADC000E} 49 | {96598D5F-199D-45E7-9F80-98FD10DCD24A} = {1E5E6DC2-39AE-4B52-83A7-46B28FEF72C3} 50 | {0D8831BD-6C91-49ED-9BE7-AEA7A6DA821F} = {1E5E6DC2-39AE-4B52-83A7-46B28FEF72C3} 51 | {E6AFFD49-C560-4947-8076-48E3F87AACAC} = {1E5E6DC2-39AE-4B52-83A7-46B28FEF72C3} 52 | {D7F4582E-2A51-4BCA-A4D6-A11B92EDAA2F} = {8618805B-A0E5-4B0A-B52D-FF5429D814E2} 53 | {020FC895-5E41-41A6-9C10-E2BCEBE40842} = {8618805B-A0E5-4B0A-B52D-FF5429D814E2} 54 | {DCFF64BC-6B91-4121-BB4B-0A34AD3A6C84} = {8618805B-A0E5-4B0A-B52D-FF5429D814E2} 55 | {12E1D11E-6E0E-4F40-91BB-996E71CC15C3} = {6BD6DACA-80E0-4683-A6B3-649D79F8994C} 56 | {A3ECA132-FE31-46DF-8715-285B41409A1D} = {8975828E-1794-41B6-8F82-41F70F52C270} 57 | EndGlobalSection 58 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 59 | {6CA5CC96-0678-4723-B5B3-E2464516C277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 60 | {6CA5CC96-0678-4723-B5B3-E2464516C277}.Debug|Any CPU.Build.0 = Debug|Any CPU 61 | {6CA5CC96-0678-4723-B5B3-E2464516C277}.Release|Any CPU.ActiveCfg = Release|Any CPU 62 | {6CA5CC96-0678-4723-B5B3-E2464516C277}.Release|Any CPU.Build.0 = Release|Any CPU 63 | {71788840-6B85-42A5-9D52-D51A802A21BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 64 | {71788840-6B85-42A5-9D52-D51A802A21BE}.Debug|Any CPU.Build.0 = Debug|Any CPU 65 | {71788840-6B85-42A5-9D52-D51A802A21BE}.Release|Any CPU.ActiveCfg = Release|Any CPU 66 | {71788840-6B85-42A5-9D52-D51A802A21BE}.Release|Any CPU.Build.0 = Release|Any CPU 67 | {5EB40414-02BE-44A5-A14C-E619914A0F4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 68 | {5EB40414-02BE-44A5-A14C-E619914A0F4A}.Debug|Any CPU.Build.0 = Debug|Any CPU 69 | {5EB40414-02BE-44A5-A14C-E619914A0F4A}.Release|Any CPU.ActiveCfg = Release|Any CPU 70 | {5EB40414-02BE-44A5-A14C-E619914A0F4A}.Release|Any CPU.Build.0 = Release|Any CPU 71 | {AD793B6C-DF05-458E-854B-ECFCAF7167AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 72 | {AD793B6C-DF05-458E-854B-ECFCAF7167AD}.Debug|Any CPU.Build.0 = Debug|Any CPU 73 | {AD793B6C-DF05-458E-854B-ECFCAF7167AD}.Release|Any CPU.ActiveCfg = Release|Any CPU 74 | {AD793B6C-DF05-458E-854B-ECFCAF7167AD}.Release|Any CPU.Build.0 = Release|Any CPU 75 | {96598D5F-199D-45E7-9F80-98FD10DCD24A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 76 | {96598D5F-199D-45E7-9F80-98FD10DCD24A}.Debug|Any CPU.Build.0 = Debug|Any CPU 77 | {96598D5F-199D-45E7-9F80-98FD10DCD24A}.Release|Any CPU.ActiveCfg = Release|Any CPU 78 | {96598D5F-199D-45E7-9F80-98FD10DCD24A}.Release|Any CPU.Build.0 = Release|Any CPU 79 | {0D8831BD-6C91-49ED-9BE7-AEA7A6DA821F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 80 | {0D8831BD-6C91-49ED-9BE7-AEA7A6DA821F}.Debug|Any CPU.Build.0 = Debug|Any CPU 81 | {0D8831BD-6C91-49ED-9BE7-AEA7A6DA821F}.Release|Any CPU.ActiveCfg = Release|Any CPU 82 | {0D8831BD-6C91-49ED-9BE7-AEA7A6DA821F}.Release|Any CPU.Build.0 = Release|Any CPU 83 | {E6AFFD49-C560-4947-8076-48E3F87AACAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 84 | {E6AFFD49-C560-4947-8076-48E3F87AACAC}.Debug|Any CPU.Build.0 = Debug|Any CPU 85 | {E6AFFD49-C560-4947-8076-48E3F87AACAC}.Release|Any CPU.ActiveCfg = Release|Any CPU 86 | {E6AFFD49-C560-4947-8076-48E3F87AACAC}.Release|Any CPU.Build.0 = Release|Any CPU 87 | {D7F4582E-2A51-4BCA-A4D6-A11B92EDAA2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 88 | {D7F4582E-2A51-4BCA-A4D6-A11B92EDAA2F}.Debug|Any CPU.Build.0 = Debug|Any CPU 89 | {D7F4582E-2A51-4BCA-A4D6-A11B92EDAA2F}.Release|Any CPU.ActiveCfg = Release|Any CPU 90 | {D7F4582E-2A51-4BCA-A4D6-A11B92EDAA2F}.Release|Any CPU.Build.0 = Release|Any CPU 91 | {020FC895-5E41-41A6-9C10-E2BCEBE40842}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 92 | {020FC895-5E41-41A6-9C10-E2BCEBE40842}.Debug|Any CPU.Build.0 = Debug|Any CPU 93 | {020FC895-5E41-41A6-9C10-E2BCEBE40842}.Release|Any CPU.ActiveCfg = Release|Any CPU 94 | {020FC895-5E41-41A6-9C10-E2BCEBE40842}.Release|Any CPU.Build.0 = Release|Any CPU 95 | {DCFF64BC-6B91-4121-BB4B-0A34AD3A6C84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 96 | {DCFF64BC-6B91-4121-BB4B-0A34AD3A6C84}.Debug|Any CPU.Build.0 = Debug|Any CPU 97 | {DCFF64BC-6B91-4121-BB4B-0A34AD3A6C84}.Release|Any CPU.ActiveCfg = Release|Any CPU 98 | {DCFF64BC-6B91-4121-BB4B-0A34AD3A6C84}.Release|Any CPU.Build.0 = Release|Any CPU 99 | {12E1D11E-6E0E-4F40-91BB-996E71CC15C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 100 | {12E1D11E-6E0E-4F40-91BB-996E71CC15C3}.Debug|Any CPU.Build.0 = Debug|Any CPU 101 | {12E1D11E-6E0E-4F40-91BB-996E71CC15C3}.Release|Any CPU.ActiveCfg = Release|Any CPU 102 | {12E1D11E-6E0E-4F40-91BB-996E71CC15C3}.Release|Any CPU.Build.0 = Release|Any CPU 103 | {A3ECA132-FE31-46DF-8715-285B41409A1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 104 | {A3ECA132-FE31-46DF-8715-285B41409A1D}.Debug|Any CPU.Build.0 = Debug|Any CPU 105 | {A3ECA132-FE31-46DF-8715-285B41409A1D}.Release|Any CPU.ActiveCfg = Release|Any CPU 106 | {A3ECA132-FE31-46DF-8715-285B41409A1D}.Release|Any CPU.Build.0 = Release|Any CPU 107 | EndGlobalSection 108 | EndGlobal 109 | --------------------------------------------------------------------------------