Slide 1

Slide 1 text

Anatomy of ASP.NET Core Requests Steve Gordon @stevejgordon | stevejgordon.co.uk Resources: http://bit.ly/aspnetanatomy

Slide 2

Slide 2 text

CLIENT HTTP REQUEST www.stevejgordon.co.uk/api/books

Slide 3

Slide 3 text

Recursive Resolver Client Root-Level DNS Top Level Domain DNS (.uk) Second-Level DNS (.co.uk) queries refers refers IP Address Domain Name Server (stevejgordon.co.uk) refers

Slide 4

Slide 4 text

Client (::64000) Web Server (101.101.121.64:443) ClientHello ServerHello Certificate ServerHelloDone ClientKeyExchange ChangeCipherSpec Finished ChangeCipherSpec Finished TCP TLS

Slide 5

Slide 5 text

@stevejgordon www.stevejgordon.co.uk GET /api/books HTTP/1.1 Host: stevejgordon.co.uk Accept: application/json, text/plain, */* Accept-Language: en-GB Accept-Encoding: br, gzip, deflate User-Agent: ClientApplication/1.0 (blank line)

Slide 6

Slide 6 text

@stevejgordon www.stevejgordon.co.uk GET /api/books HTTP/1.1 Host: stevejgordon.co.uk Accept: application/json, text/plain, */* Accept-Language: en-GB Accept-Encoding: br, gzip, deflate User-Agent: ClientApplication/1.0 (blank line)

Slide 7

Slide 7 text

@stevejgordon www.stevejgordon.co.uk GET /api/books HTTP/1.1 Host: stevejgordon.co.uk Accept: application/json, text/plain, */* Accept-Language: en-GB Accept-Encoding: br, gzip, deflate User-Agent: ClientApplication/1.0 (blank line)

Slide 8

Slide 8 text

@stevejgordon www.stevejgordon.co.uk GET /api/books HTTP/1.1 Host: stevejgordon.co.uk Accept: application/json, text/plain, */* Accept-Language: en-GB Accept-Encoding: br, gzip, deflate User-Agent: ClientApplication/1.0 (blank line)

Slide 9

Slide 9 text

KESTREL

Slide 10

Slide 10 text

Client Internet KESTREL HTTP/S R e q u e s t R e s p o n s e Accept Connection ASP.NET Core Connection Middleware Listening on :80 and :443

Slide 11

Slide 11 text

Kestrel Client Internet ASP.NET CORE {} Application Code HTTP/S HttpContext R e q u e s t R e s p o n s e Parse HTTP request

Slide 12

Slide 12 text

Kestrel Client Internet ASP.NET CORE HTTP/S HttpContext Middleware Endpoint / MVC R e q u e s t R e s p o n s e

Slide 13

Slide 13 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }

Slide 14

Slide 14 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }

Slide 15

Slide 15 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }

Slide 16

Slide 16 text

@stevejgordon www.stevejgordon.co.uk R e q u e s t R e s p o n s e Endpoint Handles Request Pipeline Invoked HttpsRedirectionMiddleware EndpointRoutingMiddleware AuthenticationMiddleware AuthorizationMiddleware EndpointMiddleware DeveloperExceptionPageMiddleware ForwardedHeadersMiddleware HostFilteringMiddleware

Slide 17

Slide 17 text

@stevejgordon www.stevejgordon.co.uk R e q u e s t R e s p o n s e Endpoint Handles Request Pipeline Invoked HttpsRedirectionMiddleware EndpointRoutingMiddleware AuthenticationMiddleware AuthorizationMiddleware EndpointMiddleware DeveloperExceptionPageMiddleware ForwardedHeadersMiddleware HostFilteringMiddleware

Slide 18

Slide 18 text

@stevejgordon www.stevejgordon.co.uk R e q u e s t R e s p o n s e Endpoint Handles Request Pipeline Invoked HttpsRedirectionMiddleware EndpointRoutingMiddleware AuthenticationMiddleware AuthorizationMiddleware EndpointMiddleware DeveloperExceptionPageMiddleware ForwardedHeadersMiddleware HostFilteringMiddleware

Slide 19

Slide 19 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Use(async (ctx, next) => { var sw = Stopwatch.StartNew(); await next(); // call next middleware in pipeline sw.Stop(); var recorder = ctx.RequestServices.GetRequiredService(); recorder.RecordRequest(ctx.Response.StatusCode, sw.ElapsedMilliseconds); }); ... }

Slide 20

Slide 20 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Use(async (ctx, next) => { var sw = Stopwatch.StartNew(); await next(); // call next middleware in pipeline sw.Stop(); var recorder = ctx.RequestServices.GetRequiredService(); recorder.RecordRequest(ctx.Response.StatusCode, sw.ElapsedMilliseconds); }); ... }

Slide 21

Slide 21 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Use(async (ctx, next) => { var sw = Stopwatch.StartNew(); await next(); // call next middleware in pipeline sw.Stop(); var recorder = ctx.RequestServices.GetRequiredService(); recorder.RecordRequest(ctx.Response.StatusCode, sw.ElapsedMilliseconds); }); ... }

Slide 22

Slide 22 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Use(async (ctx, next) => { var sw = Stopwatch.StartNew(); await next(); // call next middleware in pipeline sw.Stop(); var recorder = ctx.RequestServices.GetRequiredService(); recorder.RecordRequest(ctx.Response.StatusCode, sw.ElapsedMilliseconds); }); ... }

Slide 23

Slide 23 text

@stevejgordon www.stevejgordon.co.uk public class MetricMiddleware { private readonly RequestDelegate _next; private readonly IMetricRecorder _metricRecorder; public MetricMiddleware(RequestDelegate next, IMetricRecorder metricRecorder) { _next = next; _metricRecorder = metricRecorder; } public async Task InvokeAsync(HttpContext ctx) { var stopWatch = Stopwatch.StartNew(); await _next(ctx); stopWatch.Stop(); _metricRecorder.RecordRequest(ctx.Response.StatusCode, stopWatch.ElapsedMilliseconds); } }

Slide 24

Slide 24 text

@stevejgordon www.stevejgordon.co.uk public class MetricMiddleware { private readonly RequestDelegate _next; private readonly IMetricRecorder _metricRecorder; public MetricMiddleware(RequestDelegate next, IMetricRecorder metricRecorder) { _next = next; _metricRecorder = metricRecorder; } public async Task InvokeAsync(HttpContext ctx) { var stopWatch = Stopwatch.StartNew(); await _next(ctx); stopWatch.Stop(); _metricRecorder.RecordRequest(ctx.Response.StatusCode, stopWatch.ElapsedMilliseconds); } }

Slide 25

Slide 25 text

@stevejgordon www.stevejgordon.co.uk public class MetricMiddleware { private readonly RequestDelegate _next; private readonly IMetricRecorder _metricRecorder; public MetricMiddleware(RequestDelegate next, IMetricRecorder metricRecorder) { _next = next; _metricRecorder = metricRecorder; } public async Task InvokeAsync(HttpContext ctx) { var stopWatch = Stopwatch.StartNew(); await _next(ctx); stopWatch.Stop(); _metricRecorder.RecordRequest(ctx.Response.StatusCode, stopWatch.ElapsedMilliseconds); } }

Slide 26

Slide 26 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseMiddleware(); ... }

Slide 27

Slide 27 text

@stevejgordon www.stevejgordon.co.uk public static class MetricMiddlewareExtensions { public static IApplicationBuilder UseMetrics(this IApplicationBuilder builder) { return builder.UseMiddleware(); } }

Slide 28

Slide 28 text

@stevejgordon www.stevejgordon.co.uk public static class MetricMiddlewareExtensions { public static IApplicationBuilder UseMetrics(this IApplicationBuilder builder) { return builder.UseMiddleware(); } } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseMetrics(); ... }

Slide 29

Slide 29 text

ENDPOINT ROUTING

Slide 30

Slide 30 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }

Slide 31

Slide 31 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }

Slide 32

Slide 32 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } Routing Zone

Slide 33

Slide 33 text

@stevejgordon www.stevejgordon.co.uk public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } Endpoint Aware

Slide 34

Slide 34 text

DEMO

Slide 35

Slide 35 text

ASP.NET CORE MVC

Slide 36

Slide 36 text

@stevejgordon www.stevejgordon.co.uk [ApiController] [Route("[controller]")] public class BooksController : ControllerBase { private readonly IBookRepository _bookRepository; public BooksController(IBookRepository bookRepository) { _bookRepository = bookRepository; } [HttpGet] public ActionResult> Get() { return Ok(_bookRepository.GetAll()); } ... }

Slide 37

Slide 37 text

@stevejgordon www.stevejgordon.co.uk [ApiController] [Route("[controller]")] public class BooksController : ControllerBase { private readonly IBookRepository _bookRepository; public BooksController(IBookRepository bookRepository) { _bookRepository = bookRepository; } [HttpGet] public ActionResult> Get() { return Ok(_bookRepository.GetAll()); } ... }

Slide 38

Slide 38 text

@stevejgordon www.stevejgordon.co.uk [ApiController] [Route("[controller]")] public class BooksController : ControllerBase { private readonly IBookRepository _bookRepository; public BooksController(IBookRepository bookRepository) { _bookRepository = bookRepository; } [HttpGet] public ActionResult> Get() { return Ok(_bookRepository.GetAll()); } ... }

Slide 39

Slide 39 text

@stevejgordon www.stevejgordon.co.uk [ApiController] [Route("[controller]")] public class BooksController : ControllerBase { private readonly IBookRepository _bookRepository; public BooksController(IBookRepository bookRepository) { _bookRepository = bookRepository; } [HttpGet] public ActionResult> Get() { return Ok(_bookRepository.GetAll()); } ... }

Slide 40

Slide 40 text

@stevejgordon www.stevejgordon.co.uk Controller Initialisation Action Execution View Rendering Result Execution Response View Result Data Result Controller Factory Controller Action Invoker

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

Authorization Filters R e q u e s t R e s p o n s e Middleware Forbidden void OnAuthorization(AuthorizationFilterContext ctx)

Slide 43

Slide 43 text

Resource Filters Authorization Filters R e q u e s t R e s p o n s e Middleware Short-circuit void OnResourceExecuting(ResourceExecutingContext ctx); void OnResourceExecuted(ResourceExecutedContext ctx);

Slide 44

Slide 44 text

DEMO

Slide 45

Slide 45 text

Resource Filters Middleware Filters Authorization Filters R e q u e s t R e s p o n s e Middleware Short-circuit

Slide 46

Slide 46 text

@stevejgordon www.stevejgordon.co.uk public class CompressionMiddlewarePipeline { public void Configure(IApplicationBuilder app) { app.UseResponseCompression(); } }

Slide 47

Slide 47 text

@stevejgordon www.stevejgordon.co.uk public class CompressionMiddlewarePipeline { public void Configure(IApplicationBuilder app) { app.UseResponseCompression(); } } [ApiController] [Route("[controller]")] [MiddlewareFilter(typeof(CompressionMiddlewarePipeline))] public class AuthorsController : ControllerBase { // Action methods }

Slide 48

Slide 48 text

@stevejgordon www.stevejgordon.co.uk public class CompressionMiddlewarePipeline { public void Configure(IApplicationBuilder app) { app.UseResponseCompression(); } } [ApiController] [Route("[controller]")] [MiddlewareFilter(typeof(CompressionMiddlewarePipeline))] public class AuthorsController : ControllerBase { // Action methods }

Slide 49

Slide 49 text

Resource Filters Middleware Filters Controller Created Authorization Filters R e q u e s t R e s p o n s e Middleware

Slide 50

Slide 50 text

CONTROLLER ACTION INVOKER

Slide 51

Slide 51 text

Resource Filters Middleware Filters Controller Created Model Binding Authorization Filters R e q u e s t R e s p o n s e Middleware

Slide 52

Slide 52 text

MODEL BINDERS

Slide 53

Slide 53 text

@stevejgordon www.stevejgordon.co.uk [HttpGet] public ActionResult> Search(string keyword, int pageSize) { return Ok(_bookRepository.Search(keyword, pageSize)); } GET /books/search?keyword=performance&pageSize=10

Slide 54

Slide 54 text

@stevejgordon www.stevejgordon.co.uk [HttpGet] public ActionResult> Search(string keyword, int pageSize) { return Ok(_bookRepository.Search(keyword, pageSize)); } GET /books/search?keyword=performance&pageSize=10

Slide 55

Slide 55 text

@stevejgordon www.stevejgordon.co.uk [HttpGet] public ActionResult> Search(string keyword, int pageSize) { return Ok(_bookRepository.Search(keyword, pageSize)); } GET /books/search?keyword=performance&pageSize=10

Slide 56

Slide 56 text

@stevejgordon www.stevejgordon.co.uk [HttpGet] public ActionResult> Search(string keyword, int pageSize) { return Ok(_bookRepository.Search(keyword, pageSize)); } GET /books/search?keyword=performance&pageSize=10

Slide 57

Slide 57 text

@stevejgordon www.stevejgordon.co.uk [HttpGet] public ActionResult> Search(string keyword, int pageSize) { return Ok(_bookRepository.Search(keyword, pageSize)); } GET /books/search?keyword=performance&pageSize=10

Slide 58

Slide 58 text

@stevejgordon www.stevejgordon.co.uk [HttpPost] public IActionResult CreateBook(BookInputModel book) { // Save the Book... return Ok(); } public class BookInputModel { public int Id { get; set; } public string Title { get; set; } public string ISBN { get; set; } }

Slide 59

Slide 59 text

INPUT FORMATTERS

Slide 60

Slide 60 text

DEMO

Slide 61

Slide 61 text

Resource Filters Middleware Filters Controller Created Model Binding Authorization Filters Action Filters R e q u e s t R e s p o n s e Middleware Short-circuit void OnActionExecuting(ActionExecutingContext ctx);

Slide 62

Slide 62 text

Resource Filters Middleware Filters Controller Created Model Binding Authorization Filters Action Filters Action Execution R e q u e s t R e s p o n s e Middleware void OnActionExecuted(ActionExecutedContext ctx);

Slide 63

Slide 63 text

DEMO

Slide 64

Slide 64 text

Resource Filters Middleware Filters Controller Created Model Binding Authorization Filters Action Filters Exception Filters Action Execution R e q u e s t R e s p o n s e Middleware void OnException(ExceptionContext context);

Slide 65

Slide 65 text

DEMO

Slide 66

Slide 66 text

Resource Filters Middleware Filters Controller Created Model Binding Authorization Filters Action Filters Result Filters Exception Filters Action Execution R e q u e s t R e s p o n s e Middleware void OnResultExecuting(ResultExecutingContext ctx);

Slide 67

Slide 67 text

Resource Filters Middleware Filters Controller Created Model Binding Authorization Filters Action Filters Result Filters Exception Filters Action Execution ActionResult Executed Output Formatter R e q u e s t R e s p o n s e Middleware

Slide 68

Slide 68 text

Resource Filters Middleware Filters Controller Created Model Binding Authorization Filters Action Filters Result Filters Exception Filters Action Execution ActionResult Executed Resource Filters Middleware Filters Output Formatter R e q u e s t R e s p o n s e Middleware Result Filters void OnResultExecuted(ResultExecutedContext ctx);

Slide 69

Slide 69 text

DEMO

Slide 70

Slide 70 text

Resource Filters Middleware Filters Controller Created Model Binding Authorization Filters Action Filters Result Filters Exception Filters Action Execution ActionResult Executed Resource Filters Middleware Filters Output Formatter R e q u e s t R e s p o n s e Middleware Result Filters

Slide 71

Slide 71 text

@stevejgordon www.stevejgordon.co.uk R e q u e s t R e s p o n s e Endpoint Handles Request Pipeline Invoked HttpsRedirectionMiddleware EndpointRoutingMiddleware AuthenticationMiddleware AuthorizationMiddleware EndpointMiddleware DeveloperExceptionPageMiddleware ForwardedHeadersMiddleware HostFilteringMiddleware

Slide 72

Slide 72 text

Kestrel Client Internet ASP.NET CORE HTTP/S HttpContext Middleware MVC R e q u e s t R e s p o n s e

Slide 73

Slide 73 text

@stevejgordon www.stevejgordon.co.uk HTTP/1.1 200 OK Date: Sat, 23 May 2020 07:20:56 GMT Content-Type: application/json; charset=utf-8 Server: Kestrel Transfer-Encoding: chunked Last-Modified: Tue, 31 Mar 2020 23:00:00 GMT [{"id":1,"title":"Pro .NET Memory Management","isbn":"978-1-4842-4026- 7","datePublished":"2018-11- 13T00:00:00","authors":[{"firstName":"Konrad","lastNam e":"Kokosa"}],"lastModified":"2020-04-01T00:00:00"}]

Slide 74

Slide 74 text

@stevejgordon www.stevejgordon.co.uk HTTP/1.1 200 OK Date: Sat, 23 May 2020 07:20:56 GMT Content-Type: application/json; charset=utf-8 Server: Kestrel Transfer-Encoding: chunked Last-Modified: Tue, 31 Mar 2020 23:00:00 GMT [{"id":1,"title":"Pro .NET Memory Management","isbn":"978-1-4842-4026- 7","datePublished":"2018-11- 13T00:00:00","authors":[{"firstName":"Konrad","lastNam e":"Kokosa"}],"lastModified":"2020-04-01T00:00:00"}]

Slide 75

Slide 75 text

@stevejgordon www.stevejgordon.co.uk HTTP/1.1 200 OK Date: Sat, 23 May 2020 07:20:56 GMT Content-Type: application/json; charset=utf-8 Server: Kestrel Transfer-Encoding: chunked Last-Modified: Tue, 31 Mar 2020 23:00:00 GMT [{"id":1,"title":"Pro .NET Memory Management","isbn":"978-1-4842-4026- 7","datePublished":"2018-11- 13T00:00:00","authors":[{"firstName":"Konrad","lastNam e":"Kokosa"}],"lastModified":"2020-04-01T00:00:00"}]

Slide 76

Slide 76 text

@stevejgordon www.stevejgordon.co.uk HTTP/1.1 200 OK Date: Sat, 23 May 2020 07:20:56 GMT Content-Type: application/json; charset=utf-8 Server: Kestrel Transfer-Encoding: chunked Last-Modified: Tue, 31 Mar 2020 23:00:00 GMT [{"id":1,"title":"Pro .NET Memory Management","isbn":"978-1-4842-4026- 7","datePublished":"2018-11- 13T00:00:00","authors":[{"firstName":"Konrad","lastNam e":"Kokosa"}],"lastModified":"2020-04-01T00:00:00"}]

Slide 77

Slide 77 text

@stevejgordon www.stevejgordon.co.uk Summary • HTTP request received and parsed by Kestrel • Middleware pipeline executed • An endpoint (MVC) handles the request • Filter pipeline • Action execution • ActionResult execution

Slide 78

Slide 78 text

THANK YOU www.stevejgordon.co.uk https://app.pluralsight.com/profile/author/steve-gordon http://bit.ly/aspnetanatomy @stevejgordon