[Quick Tip] Dump the configuration easily and improve the developer experience.
Tags: dotnet
Published: 2021-05-30 16:13:18

Always knowing the state of the application is a sign that the system is under control, but sometimes this is not trivial.

Depending on the environment, it is not a simple task to access the application settings, and making this information available in the wrong location can expose vulnerabilities.

With this simple approach is possible to define a complete and safely dump for configuration settings.

### Route approache

Create an `IEndpointRouteBuilder` extensions method to encapsulate details and guarantee the right environment:

```c#
public static class EndpointRouteBuilderExtensions
{
    public static void MapDumpConfig(this IEndpointRouteBuilder endpoints, string pattern, 
        IConfigurationRoot configurationRoot, bool isProduction)
    {
        if (isProduction) return;

        endpoints.MapGet(
            pattern: pattern,
            requestDelegate: context 
                => context.Response.WriteAsync(
                    text: configurationRoot.GetDebugView(), 
                    cancellationToken: context.RequestAborted));
    }
}
```

As we can see, if the environment is the **Production** one, the configuration will be skipped.

Now, specify the middleware configuration details in `Startup.cs`, Adding a `RouteEndpoint` to the `IEndpointRouteBuilder` with `/dump-config` pattern:

```c#
public void Configure(IApplicationBuilder app)
{
    app.UseEndpoints(
            endpoints =>
                {
                    endpoints.MapDumpConfig(
                        pattern: "/dump-config",
                        configurationRoot: _configuration as IConfigurationRoot,
                        isProduction: _env.IsProduction());
                }
}
```

The resource will respond in `http://localhost/dump-config`.

### Log approache

If prefer, is it possible to deliver the dump for a log service. In this case, is not necessary the *skip* statement:

```c#
public static void MapDumpConfig(this IEndpointRouteBuilder endpoints, string pattern, 
    IConfigurationRoot configurationRoot, ILogger logger)
{
    endpoints.MapGet(
        pattern: pattern,
        requestDelegate: context =>
            {
                logger.LogInformation("{Settings}", configurationRoot.GetDebugView());
                
                return context.Response.WriteAsync(
                    text: "Configuration dumped successfully.", 
                    cancellationToken: context.RequestAborted);
            });
}
```

And then, propagate the log resource:

```c#
public void Configure(IApplicationBuilder app , ILoggerFactory loggerFactory)
{
        app.UseEndpoints(
            endpoints =>
                {
                    endpoints.MapDumpConfig(
                        pattern: "/dump-config",
                        configurationRoot: _configuration as IConfigurationRoot,
                        logger: loggerFactory.CreateLogger<Startup>());
                }
}
```

### Multiple strategy approache

```c#
public static void MapDumpConfig(this IEndpointRouteBuilder endpoints, string pattern, 
    IConfigurationRoot configurationRoot, bool isProduction, ILogger logger)
{
    endpoints.MapGet(
        pattern: pattern, 
        requestDelegate: context 
            => isProduction ? DumpToLogAsync(context) : DumpToResponseAsync(context));

    Task DumpToResponseAsync(HttpContext context)
        => context.Response.WriteAsync(
            text: configurationRoot.GetDebugView(), 
            cancellationToken: context.RequestAborted);
    
    Task DumpToLogAsync(HttpContext context)
    {
        logger.LogInformation("{Settings}", configurationRoot.GetDebugView());
        
        return context.Response.WriteAsync(
            text: "Configuration dumped successfully", 
            cancellationToken: context.RequestAborted);
    }
}
```

#### Conclusion

In this way, we can improve the developer experience given a simple way to check the actual state of the system.