Continuing a blog series on Jasper functionality:
- Jasper’s Configuration Story
- Jasper’s Extension Model
- Integrating Marten into Jasper Applications
- Durable Messaging in Jasper
- Integrating Jasper into ASP.Net Core (this one)
- Jasper’s HTTP Transport
- Jasper’s “Outbox” Support within ASP.Net Core Applications
There will be some need for completely headless services written with Jasper that rely strictly on TCP connections or yet to come queueing transports, but I expect that most of the systems at work where we’ll use Jasper will be within ASP.Net Core applications.
Moreover, as a nasty lesson learned from my hubristic attempts at creating a freestanding development ecosystem with FubuMVC, Jasper is meant to be merely a good citizen within the greater server side ASP.Net Core ecosystem. In regards to this blog post, that means using as much of the standard Hosting model as possible. For example, Jasper supports the IHostedService model from ASP.Net Core out of the box for long running background services or startup and shutdown actions.
As of Jasper 0.6, I pulled the HTTP support and ASP.Net Core integration into a separate Jasper.Http
Nuget. This might feel like the tail wagging the dog, but I really only did this to optimize the core Jasper testing suite because bootstrapping ASP.Net Core on every integration test was slowing the automated build down too much. If I can find a way to optimize or at least parallelize much more of the bootstrapping with the messaging, I will consider merging things back together again later.
When Jasper is integrated into an ASP.Net Core system, it:
- Adds more service registrations to the application
- Bootstraps the
JasperRuntime
object and places that within the container so that the Jasper transports will be cleanly shut down when theIWebHost
is disposed - Replaces the built in DI container with Lamar (Jasper only works with Lamar at this point)
- Jasper also sneaks in some ASP.Net Core middleware to add its own routes into the application, which I’ll show off in the next post about Jasper’s HTTP messaging transport
All of this is documented in the Jasper Getting Started page and in the specific documentation for ASP.Net Core integration.
Longer term, I might try to move Jasper closer to the existing ASP.Net Core bootstrapping mechanisms.
Bootstrapping ASP.Net Core the Idiomatic Jasper Way
The first option is really about adding HTTP support to an idiomatic Jasper application. In this case, you just use the JasperHttpRegistry
from the Jasper.Http
library as the base class for your application definition like so:
public class AppWithMiddleware : JasperHttpRegistry { public AppWithMiddleware() { // Do the normal stuff you do to configure // service registrations, configuration, and // messaging support Http.Configure(app => { app.UseMiddleware<CustomMiddleware>(); // Explicitly control the order in which the Jasper // middleware is placed within the ASP.Net Core // pipeline. app.AddJasper(); // Just to show how you can configure ASP.Net Core // middleware that runs after Jasper's RequestDelegate, // but do note that Jasper has its own default "not found" // behavior app.Run(c => { c.Response.StatusCode = 404; return c.Response.WriteAsync("Not found"); }); }); } }
A couple things to note:
- The
Http
property in the class shown above is just theIWebHostBuilder
interface you’re already used to if you use ASP.Net Core today - If the call to
IApplicationBuilder.AddJasper()
is omitted, Jasper will add its own middleware to the very end of the pipeline - The HTTP bootstrapping in the idiomatic model is somewhat parallelized with the messaging support bootstrapping
- I’d argue that this usage makes the ASP.Net Core StartUp conventional configuration model unnecessary, but you’re perfectly able to continue using that if you want.
I hope to do more optimizations to the cold startup time in the future for the idiomatic Jasper approach that would make this option be more attractive. Right now, the biggest reason to use this approach over the following is to be able to use Jasper’s console application harness and Storyteller integration.
Adding Jasper to an Existing ASP.Net Core System
You can also add Jasper to an existing ASP.Net Core system using its idiomatic bootstrapping approach. In this case, you still start with the JasperHttpRegistry
base class from the Jasper.Http
library, but you mostly use this to configure the messaging support:
public class SimpleJasperBusApp : JasperHttpRegistry { public SimpleJasperBusApp() { // Enable the HTTP messaging transport Http.Transport.EnableListening(true); // Listen for TCP messages at port 2222 Transports.LightweightListenerAt(2222); } }
Then, to add the Jasper support to your ASP.Net Core application, you would add these calls:
var builder = new WebHostBuilder(); builder .UseKestrel() .UseUrls("http://localhost:3003") .UseStartup<Startup>() // This *has* to be the last call // to your IWebHostBuilder .UseJasper<SimpleJasperBusApp>(); theHost = builder.Build(); theHost.Start();
I hate this from a usability perspective, but for right now, the call to UseJasper()
has to be added after any other IStartUp
registration including the UseStartup<T>()
method. You still have the same ability to explicitly control the order of the Jasper middleware within your ASP.Net Core middleware pipeline.