Adding Jasper to an ASP.Net Core Application Edit on GitHub


This functionality is very likely to change as it gets used more often and should be considered very preliminary

.Net is Microsoft's world, and the rest of us are just living in it. Unlike its predecessor FubuMVC, Jasper tries to play nice as a citizen in the greater ASP.Net Core ecosystem. To that end, you can use Jasper within an ASP.Net Core application as just a service bus or command executor or as just another part of the ASP.Net Core runtime pipeline.

If ASP.Net Core is in charge...

Note! At the moment, the UseJasper() method has to be the very last declaration against IWebHostBuilder for the timing of actions to work correctly. We think that we'll be able to address this with some changes to hosting that are coming in ASP.Net Core 2.0

First off, let's say that you just want to use Jasper as messaging infrastructure inside of an ASP.Net Core application. With that in mind, let's say that you have a JasperRegistry like this:


public class SimpleJasperBusApp : JasperRegistry

If you prefer to stick with the idiomatic ASP.Net Core bootstrapping, you can add Jasper to the mix with the UseJasper() extension method as shown below:


var builder = new WebHostBuilder();
builder
    .UseKestrel()
    .UseUrls("http://localhost:3003")
    .UseStartup<Startup>()
    .UseJasper<SimpleJasperBusApp>();


theHost = builder.Build();

theHost.Start();

There's a couple things going on in the sample above:

  1. Jasper is quietly replacing the ASP.Net Core IoC container with Jasper's internal StructureMap container after pulling in all the service registrations made directly to the IWebHostBuilder. For the moment, we're doing this under the belief that it's best to avoid having two different IoC containers at runtime.
  2. If you don't specify exactly where you want Jasper to run within the middleware pipeline of your ASP.Net Core application, Jasper puts itself as the very last RequestDelegate in the middleware chain.
  3. The UseJasper() method is bootstrapping the JasperRuntime and putting that into the IoC container, so that disposing the IWebHost will also shut down the Jasper services as well.

To control the order of where Jasper executes within your ASP.Net Core application pipeline, you can explicitly add the Jasper middleware like this:


var builder = new WebHostBuilder();
builder
    .UseKestrel()
    .UseUrls("http://localhost:3003")
    .Configure(app =>
    {
        app.UseMiddleware<CustomMiddleware>();

        // Add the Jasper middleware
        app.AddJasper();

        // Nothing stopping you from using Jasper *and*
        // MVC, NancyFx, or any other ASP.Net Core
        // compatible framework
        app.AddMvc();
    })
    .UseJasper<SimpleJasperBusApp>();


theHost = builder.Build();

theHost.Start();

If Jasper is in charge...

Doing the bootstrapping the idiomatic Jasper way allows Jasper to parallelize quite a bit of the bootstrapping behavior for faster startup times.

If you choose to use Jasper idiomatically, it can bootstrap ASP.Net Core itself if you're using the HTTP features. JasperRegistry.Http exposes the ASP.Net IWebHostBuilder to configure the Http hosting as shown below:


public class JasperServerApp : JasperRegistry
{
    public JasperServerApp()
    {
        Messaging.Handlers.ConventionalDiscoveryDisabled = true;

        Http
            .UseKestrel()
            .UseUrls("http://localhost:3002")
            .UseStartup<Startup>();

    }
}

In the case above, Jasper will automatically configure itself as the RequestDelegate for the application.

To get more precise with how ASP.Net Core middleware is ordered with Jasper, you can again use the AddJasper() extension method:


public class AppWithMiddleware : JasperRegistry
{
    public AppWithMiddleware()
    {
        Http.Configure(app =>
        {
            app.UseMiddleware<CustomMiddleware>();

            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");
            });
        });
    }
}