ASP.NET Core Middleware - · PDF fileEXPOWARE SOFT - 2016 Coordinating Multiple Middleware...

28
EXPOWARE SOFT - 2016 Dino Esposito ASP.NET Core Middleware @despos facebook.com/naa4e Press

Transcript of ASP.NET Core Middleware - · PDF fileEXPOWARE SOFT - 2016 Coordinating Multiple Middleware...

EXPOWARE SOFT - 2016

Dino Esposito

ASP.NET Core Middleware

@despos facebook.com/naa4e Press

EXPOWARE SOFT - 2016

IIS and ASP.NET forever together

EXPOWARE SOFT - 2016

Then it came OWIN…

OWIN is a specification on how web servers and web applications should be built in order to decouple one from another.

and allow ASP.NET applications to run in environments different from IIS

http://owin.org/

EXPOWARE SOFT - 2016

Web

Forms

MVC

Web API

system.web MVC model

Katana

ASP.NET Core

SignalR

EXPOWARE SOFT - 2016

New Pipeline

EXPOWARE SOFT - 2016

New and Old Pipeline

HTTP module

IISASP.NET

HTTP module

Process

RequestInternet

EXPOWARE SOFT - 2016

Kestrel

Minimalistic web server for ASP.NET Core

Based on libuv, multi-platform library for async I/O

Not a fully-fledged web server

Better if standing behind a reverse proxy

- i.e., NGINX

EXPOWARE SOFT - 2016

Reverse ProxyRetrieves resources on behalf of a client from one or more servers.

REVERSE PROXY

KestrelProtected from

direct accessPrimary reason is security

EXPOWARE SOFT - 2016

Reverse vs. Forward

BROWSER

ACTUALSERVER

BROWSER

ACTUALSERVER

REVERSE PROXY PROXY

EXPOWARE SOFT - 2016

public class Program{

public static void Main(){

var host = new WebHostBuilder().UseKestrel().UseUrls("http://localhost:5000").UseStartup<Startup>().Build();

host.Run();}

}UseIISIntegration()to configure IIS as reverse proxy

EXPOWARE SOFT - 2016

Startup

Middleware to be added to the pipeline and configured

Only configured middleware runs

Nothing like “free” middleware

All you have is only all you add (and configure)

EXPOWARE SOFT - 2016

Startup

Middleware to be added to the pipeline and configured

Only configured middleware runs

Nothing like “free” middleware Not even static files

All you have is only all you add (and configure)

EXPOWARE SOFT - 2016

public class Startup{

public void ConfigureServices(IServiceCollection services){

// Add services here}

public void Configure(IApplicationBuilder app){

app.Run(async (context) =>{

await context.Response.WriteAsync(DateTime.Now)});

}}

EXPOWARE SOFT - 2016

Static Files

public void Configure(IApplicationBuilder app){

app.UseStaticFiles();app.UseDefaultFiles();

}

Default root folder is wwwroot

Change it with UseWebRoot("Content") in program.cs

ContentRoot vs WebRoot

EXPOWARE SOFT - 2016

Static Files—more control

public void Configure(IApplicationBuilder app){

app.UseStaticFiles(); // wwwroot

app.UseStaticFiles(new StaticFileOptions(){

FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @"Content"),

RequestPath = new PathString("/Assets")});

}

EXPOWARE SOFT - 2016

Static Files—even more control

public void Configure(IApplicationBuilder app){

app.UseStaticFiles(new StaticFileOptions(){

OnPrepareResponse = ctx =>{

ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=600");

}});

}

No authorization checks on static files. Go through your own controllers.

EXPOWARE SOFT - 2016

Mini Web Server

public void Configure(IApplicationBuilder app){

app.Run(async (context) =>{

var code = context.Request.Query["c"];var size = context.Request.Query["s"];var file = FindAndResizeFlag(code, file);

await context.Response.SendFileAsync(file);});

}

EXPOWARE SOFT - 2016

Extreme Granularity

public void ConfigureServices(IServiceCollection services){

services.AddMvc();}

public void ConfigureServices(IServiceCollection services){

var builder = services.AddMvcCore();builder.AddViews();builder.AddRazorViewEngine();builder.AddJsonFormatters();

}

EXPOWARE SOFT - 2016

// Any chunk like this adds custom behaviorapp.Use(async (context, nextMiddleware) =>{

// first pass here

await nextMiddleware(); // optional, but ...

// second pass here});

EXPOWARE SOFT - 2016

Terminating middleware

// Proceeds to the end of the list of registered middleware components;// Then back to the beginning in the reverse order.

app.Run(async context =>{

await context.Response.WriteAsync("...");});

Terminating middleware may work as a catch-all route for MVC routes

EXPOWARE SOFT - 2016

public delegate Task RequestDelegate(HttpContext context);

Signature of a piece of ASP.NET Core middleware

Register middleware with Use(func)

app.Use(async (context, next) => {

// ...});

EXPOWARE SOFT - 2016

Acting on routes

app.Map(url, middleware =>{

middleware.Run( ... );});

public static IAppBuilder Map(this IAppBuilder app, PathString pathMatch, Action<IAppBuilder> configuration)

app.MapWhen(ctx => IsConditionVerified(ctx), middleware =>{

middleware.Run( ... );});

EXPOWARE SOFT - 2016

Coordinating Multiple Middleware

Always be a good citizen- Keep in mind headers can’t be written anymore once the body has begun

- Think before you write to the body

- Document clearly when and how you might be writing to the body

Always be a good neighbor- Be on the safe side

- Register your headers to be added at the last possible minute before the

body is written

EXPOWARE SOFT - 2016

Writing Headers from the Middleware

app.Use(async (context, nextMiddleware) =>{

context.Response.OnStarting(() =>{

context.Response.Headers.Add("hello", "world");return Task.FromResult(0);

});

await nextMiddleware();});

EXPOWARE SOFT - 2016

Middleware Conventions

public class YourMiddleware{

private RequestDelegate _next; public YourMiddleware(RequestDelegate middleware) {

_nextMiddleware = middleware; }

public async Task Invoke(HttpContext context) {

// Possibly do something here before yielding_nextMiddleware(context);

} }

EXPOWARE SOFT - 2016

Middleware Conventions—extension methods

public static class YourMiddlewareExtensions{

public static IApplicationBuilder UseYours(this IApplicationBuilder builder)

{return builder.UseMiddleware<YourMiddleware>();

}}

public void Configure(IApplicationBuilder app) {

app.UseYours(); }

EXPOWARE SOFT - 2016

Scoping Services

public class YourMiddleware{

private RequestDelegate _next; public YourMiddleware(RequestDelegate middleware) {

_nextMiddleware = middleware; }

public async Task Invoke(HttpContext ctx, ISomeService svc) {

// Possibly do something here before yielding_nextMiddleware(ctx);

} }

Per-request

dependency

EXPOWARE SOFT - 2016