ASP.NET Core Middleware - · PDF fileEXPOWARE SOFT - 2016 Coordinating Multiple Middleware...
Transcript of ASP.NET Core Middleware - · PDF fileEXPOWARE SOFT - 2016 Coordinating Multiple Middleware...
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
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