Configuring ASPNET Core Apps with WebHostBuilder

In ASP.NET Core apps, you typically configure the application in Startup. However, the application itself runs inside of a host, which is configured separately using a WebHostBuilder. Although it’s not the default, recommended case (and thus isn’t shown in the official docs), you can actually configure the application directly from WebHostBuilder and avoid using a Startup class entirely (or augment what Startup is able to do). These techniques can come in handy in certain scenarios, including integration tests, which I’ll use in this post to demonstrate different kinds of WebHostBuilder configurations. View all of the tests and run them yourself from this repo.

When using Startup, you must implement the Configure method (to set up the app’s request pipeline) and optionally the ConfigureServices method (to configure any dependencies the app needs to have registered). You can do either or both of these things directly within WebHostBuilder via its Configure() and ConfigureServices() extension methods. For example:

This integration test configures a host to return “Hi” to all requests, and then confirms that “Hi” is returned when a request is made to the root of the application.

Within Startup, you can leverage dependency injection in the constructor and in the Configure method. Normally, only a few known framework types are available to you, such as IApplicationBuilder or IHostingEnvironment. However, using WebHostBuilder you can configure services before Startup is instantiated, making additional services available to be injected into Startup’s constructor and/or Configure method (ConfigureServices can access these services directly from its IServiceCollection parameter).

This Startup class requests an instance of IGreeting in its Configure method:

Normally, this would fail, but you can provide the required service using WebHostBuilder, as this test demonstrates:

Finally, debugging problems that occur in your app’s Startup method can be difficult, since usually at that point error pages and logging are not yet configured. One approach that can be helpful is to configure logging from the WebHostBuilder, so that you can log what’s happening in Startup. For example, this Startup class requests an ILogger<T> in its constructor:

Its logger is configured in WebHostBuilder to use a ConsoleLogger:

You can view the log output when you run dotnet test from the console.

Similarly, you can pass the logger into the Configure method directly, rather than the constructor:

And it works the same. Note that passing in loggers like this, which will use the ILoggerFactory service behind the scenes, is supported without any special configuration via WebHostBuilder. All I’m doing here is making sure a Console logger is wired up in WebHostBuilder so that when Startup executes I’m able to view the log output in the console.

Having logging configured and available to Startup can be a big help to diagnosing issues that occur there. Normally, application logging isn’t configured until the Configure method is called, which is after the constructor and ConfigureServices have already run, so there’s no opportunity to log what goes on in those earlier methods. Using WebHostBuilder, logging (and other services) can be configured prior to Startup running at all, making these services available to all three of Startup’s main methods (constructor, Configure, and ConfigureServices).