Being part of a community means being inspired by other folks’ work to learn, get better, and add our value back in. When I read Jeremy Miller’s Oakton post about running development-time commands, I was inspired to contribute. Being hosted in ASP.NET, it also reminded me of Andrew Lock’s ApiExplorer about introspecting our API and learning more about the make-up of our applications.

In this post, we’ll use both Oakton and ApiExplorer to build a development-time command to list all the routes in our app directly into our console. For bonus points, we’ll also use JetBrains Rider to display them in our IDE’s terminal.

List Routes Command

We can start by cloning Jeremy’s GitHub repository sample. We’ll be supplementing the existing action with our new ListRoutesCommand. We will also need to install ConsoleTables.

> dotnet install ConsoleTables

Let’s add the ListRoutesCommand class now. We’ll explain the different parts afterwards.

[Description("List all routes in web api")]
public class ListRoutesCommand : OaktonCommand<NetCoreInput>
{
    public override bool Execute(NetCoreInput input)
    {
        using var host = input.BuildHost();
        var serviceType = typeof(IApiDescriptionGroupCollectionProvider);

        if (!(host
            .Services
            .GetService(serviceType) is IApiDescriptionGroupCollectionProvider explorer)) 
            return true;
        
        var results = explorer
            .ApiDescriptionGroups
            .Items
            .SelectMany(x => x.Items)
            .Select(x => new
            {
                x.RelativePath,
                x.HttpMethod,
                Controller = x.ActionDescriptor.RouteValues["controller"],
                Action = x.ActionDescriptor.RouteValues["action"],
                Parameters = string.Join(", ", x.ParameterDescriptions.Select(p => $"{p.Name} ({p.Type.Name})"))
            })
            .ToList();
            
        Console.Clear();
        Console.WriteLine();
            
        ConsoleTable
            .From(results)
            .Write();

        return true;
    }
}

The fantastic part of Oakton is that it allows us access to our ASP.NET application, which gives us access to all our dependency injection services. Having access to the ServiceCollection means we can request an instance of IApiDescriptionGroupCollectionProvider which describes our API endpoints.

We need to map some of the more important values of our API into a collection, which we’ll use to write out to the console output window.

var results = explorer
    .ApiDescriptionGroups
    .Items
    .SelectMany(x => x.Items)
    .Select(x => new
    {
        x.RelativePath,
        x.HttpMethod,
        Controller = x.ActionDescriptor.RouteValues["controller"],
        Action = x.ActionDescriptor.RouteValues["action"],
        Parameters = string.Join(", ", x.ParameterDescriptions.Select(p => $"{p.Name} ({p.Type.Name})"))
    })
    .ToList();
    
Console.Clear();
Console.WriteLine();
    
ConsoleTable
    .From(results)
    .Write();

We can now run our listroutes command from the command-line.

> dotnet run listroutes

We can expect to see the following output.

oakton route values

Awesome!

JetBrains Rider Runner

If we’re users of JetBrains Rider, we can set up our IDE to run the command using a build configuration. We first need to edit our build configurations.

jetbrains rider edit configurations

We follow it up by adding a new .NET Project configuration using the + symbol.

jetbrains rider add .net project build

We can then add our Oakton command as one of the program arguments. In our case, it will be listroutes.

jetbrains rider program arguments

Finally, we can run our command like we would any build command and see the results in a new run window.

jetbrains rider build runner

The ability to push a button should make the GUI lover in all of us very happy. We could also promote our runner to a launch setting so our team can share in all this great value.

Conclusion

It’s always fun to be inspired and spike a new idea. Oakton seems like a compelling addition to any ASP.NET project, especially for those looking to automate their development process. I hope you found this post fun, and leave a comment below if you have your ideas for Oakton development commands.