New Gas Fireplace

The unused, unlit, unloved wood burning fireplace in our house needed some attention. I started by teeing off of the line I previous installed to run the garage heater.

Unfortunately the pipe had to be moved away from the wall to account for this, but now the main house gas line couldn’t reach the tee! I ended up wrapping around the pipe and using a union to get it connected.

I ran the gas line through into the crawlspace along the joists to the fireplace. I added some temporary support while drilling the hole in the subfloor for the gas valve key. Once it was lined up and drilled I affixed the gas pipe to the joist for a secure connection. After going through the key valve I ran the gas line outside and along the side of the chimney, supported with Unistrut channel and brackets along the way.

I used a rotary hammer and a long bit to drill through the brick to the outside of the house. I ran the gas line in through the hole from outside.

I originally underestimated how thick the fireplace was!

Had to go back to the store for a larger bit

Since the fireplace has a working chimney with flue I decided to use a normal gas fireplace instead of an insert or something that doesn’t require an actual chimney. Flexible gas line connected to the fireplace, all that was left was wood!

In the video you can still see the gas line, afterwards I purchased 15lbs of lava rock and poured it around the outside of the fireplace to hide the grate and the gas line.

Validating configuration on startup in ASP.Net core 2.2

The ability to validate configurations in Startup.cs was pushed from .NET Core 2.2 to 3.0. In the mean time I still needed to validate our configurations when they were loaded to ensure all transforms performed correctly and no configuration fields were missing. I found a few solutions online for this, but they involved middleware like Andrew Lock’s solution or using the services.Configure pattern like Vidar Kongsli’s solution. I needed something simpler and easier for developers to implement.

Configuring services in Startup.cs looked like

var cognitoConfiguration = configuration.GetSection("Aws-Cognito").Get<AwsCognitoConfiguration>();
           services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
   .AddJwtBearer(options =>
   {
      options.Audience = cognitoConfiguration.UserPoolClientId;
      options.Authority = cognitoConfiguration.AuthorityUrl.ToString();
   });

But issues can arise with this approach, for instance if UserPoolClientId isn’t populated, or if the entire 'Aws-Cognito' section was missing from the appsettings.json. A simple approach is to create an extension method for the IConfiguration class:

public static class ConfigurationExtensionMethods
{
     public static T GetSectionAndValidate<T>(this IConfiguration configuration, string sectionName)
         where T : DriveConfiguration
     {
         var results = configuration.GetSection(sectionName).Get<T>();

         results.CheckConfigurationValid();

         return results;
     }
 }

Modify all of the configuration POCO’s to use an abstract class for the validation:

public abstract class DriveConfiguration
{
    public void CheckConfigurationValid()
    {
        var results = new List<ValidationResult>();

        var isValid = Validator.TryValidateObject(
            this,
            new ValidationContext(this),
            results,
            true);

        if (!isValid)
        {
            var errorMessage = $"Missing configuration for {this.GetType().Name}: ";

            errorMessage += string
                .Join(", ", results
                    .Select(x => x.ErrorMessage));

            throw new ArgumentException(errorMessage);
        }
    }
}

A configuration POCO then uses theSystem.ComponentModel.DataAnnotations namespace to add validation attributes like [Required] or [EmailAddress]:

public class AwsCognitoConfiguration : DriveConfiguration
{
   [Required]
   public string UserPoolClientId { get; set; }

   [Required]
   public Uri AuthorityUrl { get; set; }
}

in Startup.cs getting the configuration changes to look like:

var cognitoConfiguration = _configuration.GetSectionAndValidate<AwsCognitoConfiguration>("Aws-Cognito");

When the GetSectionAndValidate<T>() executes, it populates the configuration POCO from appsettings.json and then fires off the validation. Aside from using the extension method, nothing else needs to be done in order for all configurations in Startup.cs to be validated automatically! Exceptions look like

System.ArgumentException: 'Missing configuration for CognitoConfiguration: The UserPoolClientId is required'

As you can see, it’s very easy to see what value is missing from what part of appsettings.json. This validation can be used for a health check, or even cause launch failures that an ECS cluster can respond to.

.Net Core 2.2 comes with a good base set of validators, but writing your own validator attributes is as easy as implementing ValidationAttribute:

[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class AwsAccessKeyValidatorAttribute : ValidationAttribute
{
    public AwsAccessKeyValidatorAttribute()
        : base("The {0} field must be a valid AWS Access Key")
    {
    }

    public override bool IsValid(object value)
    {
        return value is string && value.ToString().Trim().Length == 20;
    }
}

To Infinity, Recursively!