Jasper in Console Applications Edit on GitHub


At this time, the Jasper team is focused on hosting applications either in IIS (or nginx) or as a console application that would be suitable for running in a Docker container. To that end, we've added the JasperAgent static class in the external Jasper.CommandLine Nuget library as a helper for quickly standing up Jasper applications in a console application.

The sample usage from the getting started topic would look like this:



using Jasper.CommandLine;

namespace MyApp
{
    class Program
    {
        static int Main(string[] args)
        {
            // This bootstraps and runs the Jasper
            // application as defined by MyAppRegistry
            // until the executable is stopped
            return JasperAgent.Run<MyAppRegistry>(args);
        }
    }
}

At runtime, JasperAgent uses the JasperRegistry you hand it to bootstrap a JasperRuntime and run the application until the console process is stopped.

You can also use the command line arguments to customize how the application runs like this:


static int Main(string[] args)
{
    return JasperAgent.Run<MyAppRegistry>(args, _ =>
    {
        if (args.Length == 1)
        {
            _.EnvironmentName = args[0];
        }
    });
}

Or like this:


static int Main(string[] args)
{
    // This gives you the ability to programmatically
    // construct the application based on the command line
    // arguments
    var registry = new JasperRegistry();


    return JasperAgent.Run(args, registry);
}

Let's say that your Jasper application compiles to MyApp.exe and uses the JasperAgent class to run the commands. In that case you can run your application simply by typing MyApp at the command line with no arguments.

However, the Jasper.CommandLine library adds some additional commands for running, validating, or describing the running application.

Overriding the Environment Name

For example, you can also use this syntax to run your application in "Development" mode:

MyApp run --environment Development

or

MyApp run -e Development

If you run this command, your application will start with JasperRegistry.EnvironmentName equal to Development. If you programmatically set the environment name in your JasperRegistry, that setting will win out over the command line flag.

Running with Verbose Console Tracing

Likewise, to see more verbose information on start up and runtime console tracing, use:

MyApp run --verbose

or

MyApp run -v

Validating the Configured Application

You may want to simply try to bootstrap the application and run all the environment tests and report out the results. That syntax is:

MyApp validate

which also respects the same --environment and --verbose flags as the run command. This command will bootstrap the application, run all the environment tests and start up validations, report on the success or failure, and shut down the application. Do note that if any environment tests fail, this command will return a non-zero return code that should be sufficient to let any build scripting tool you're using know that the validation failed.

List Registered Services

This is in flight

As of right now (Dec 2017), Jasper only supports the StructureMap container, but is somewhat likely to transition to, um, something else (or a streamlined, faster StructureMap) to be named later before it hits 1.0. Regardless, we expect this command will live on.

To bootstrap the application and list out all the services registered to the system's IoC container, use this command:

MyApp services

And again, this command respects both the --environment and --verbose flags

Subscriptions

See Dynamic Subscriptions for information about the subscriptions command and related workflow for exporting, updating, or validating dynamic subscriptions.

Custom Commands

The Jasper.Console package uses the Oakton library for its command line support. You can add custom commands to your Jasper application by simply including OaktonCommand<T> classes in either the main application assembly or in any assembly that is decorated with the [JasperModule] attribute like so:


[assembly:JasperModule(typeof(DiagnosticsExtension))]

or without any kind of extension like so:


[assembly:JasperModule]

If you want to write a command that uses the actual Jasper application, use the JasperInput class as either the input to your command or as the superclass to your input class:


public class JasperInput
{
    [IgnoreOnCommandLine]
    public JasperRegistry Registry { get; set; }

    [Description("Use to override the ASP.Net Environment name")]
    public string EnvironmentFlag { get; set; }

    [Description("Write out much more information at startup and enables console logging")]
    public bool VerboseFlag { get; set; }

    [Description("Override the log level")]
    public LogLevel? LogLevelFlag { get; set; }

    public JasperRuntime BuildRuntime()
    {
        if (LogLevelFlag.HasValue)
        {
            Registry.ConfigureLogging(x => x.SetMinimumLevel(LogLevelFlag.Value));
        }

        if (VerboseFlag)
        {
            Console.WriteLine("Verbose flag is on.");

            Registry.ConfigureLogging(x =>
            {
                x.SetMinimumLevel(LogLevel.Debug);

                x.AddConsole();
                x.AddDebug();
            });
        }

        if (EnvironmentFlag.IsNotEmpty())
        {
            Registry.UseEnvironment(EnvironmentFlag);
        }

        return JasperRuntime.For(Registry);
    }
}

To make that more concrete, here is how the built in services command uses JasperInput type to build out and use the running system:


[Description("Display the known StructureMap service registrations")]
public class ServicesCommand : OaktonCommand<JasperInput>
{
    public override bool Execute(JasperInput input)
    {
        input.Registry.Settings.Alter<MessagingSettings>(_ =>
        {
            _.ThrowOnValidationErrors = false;
        });

        using (var runtime = input.BuildRuntime())
        {
            Console.WriteLine(runtime.Container.WhatDoIHave());
        }

        return true;
    }
}

Do note that the command will be responsible for disposing and shutting down the running JasperRuntime.