Middleware implementation in ASP.Net Core is weird
This might seem like a clickbait-y article, but… it really looks this way! Allow me to explain.
For one of my pet projects, I considered implementing REST endpoints using Nancy, a nice and low ceremony web framework that I like.
To my surprise, in order to host it in .Net Core, as evident from the example here, I would need to use Microsoft.AspNetCore.Owin as a “mediator” between Kestrel and Nancy. Seeing this as an excuse to write something in the area I haven’t looked into yet, I looked into implementing a middleware component to run Nancy engine directly. (You can find what I wrote in NuGet or in Github)
To my surprise, a minimal middleware implementation looks like this:
1 | public class FoobarMiddleware |
And then, in the Startup class of ASP.Net Core initialization, the middleware is “registered” like this:
1 | internal class Startup |
This seemed like too much “magic” happening - I would expect the middleware class to be required to implement abstract class or interface in an API like this. I don’t like too much magic happening in my code so I decided to take a look at ASP.Net Core implementation and look at the UseMiddleware<T>()
source.
Well, the relevant part looks like this:
1 | public static class UseMiddlewareExtensions |
It turns out ASP.Net Core uses reflection to check if middleware class implements either Invoke or InvokeAsync methods AND uses reflection to instantiate it.
This is a weird choice, I think. Why use reflection when the same can be achieved at compile time using interface inheritance? Is it a good practice? A good question, to which (at least for now) I don’t have an answer.