Search code examples
csvhelper

CSVHelper mapping not picking up when column is missing


I've been using the CSVHelper and I must say that it is absolutely fantastic. I'm having an issue though with the mapping when the column is not in the file.

using (var stream = client.GetDownloadStream(string.Format("{0}{1}", _remoteFileDirectoryExports, remoteFileName)))
{
    using (var s = new StreamReader(stream))
    {
        var csv = new CsvReader(s, new Configuration()
        {
            HasHeaderRecord = true,
            HeaderValidated = null,
            MissingFieldFound = null
        });

        csv.Configuration.RegisterClassMap<EverTrueInteractionMap>();

        records = new List<T>();

        foreach (var r in csv.GetRecords<T>())
        {
            records.Add(r);
        }
    }
}

My mapping class is below.

public class EverTrueInteraction
{
    public string InteractionImportId { get; set; }     
    public string Solicitor1ImportId { get; set; }
    public string Solicitor1EverTrueId { get; set; }
    public string Solicitor1Name { get; set; }
    public string Solicitor2ImportId { get; set; }
    public string Solicitor2EverTrueId { get; set; }
    public string Solicitor2Name { get; set; }
    public string Solicitor3ImportId { get; set; }
    public string Solicitor3EverTrueId { get; set; }
    public string Solicitor3Name { get; set; }
    public string Solicitor4ImportId { get; set; }
    public string Solicitor4EverTrueId { get; set; }
    public string Solicitor4Name { get; set; }
    public string Solicitor5ImportId { get; set; }
    public string Solicitor5EverTrueId { get; set; }
    public string Solicitor5Name { get; set; }
}

public sealed class EverTrueInteractionMap : ClassMap<EverTrueInteraction>
{
    public EverTrueInteractionMap()
    {
        AutoMap();
        Map(m => m.Solicitor1ImportId).Default("");
        Map(m => m.Solicitor1EverTrueId).Default("");
        Map(m => m.Solicitor1Name).Default("");
        Map(m => m.Solicitor2ImportId).Default("");
        Map(m => m.Solicitor2EverTrueId).Default("");
        Map(m => m.Solicitor2Name).Default("");
        Map(m => m.Solicitor3ImportId).Default("");
        Map(m => m.Solicitor3EverTrueId).Default("");
        Map(m => m.Solicitor3Name).Default("");
        Map(m => m.Solicitor4ImportId).Default("");
        Map(m => m.Solicitor4EverTrueId).Default("");
        Map(m => m.Solicitor4Name).Default("");
        Map(m => m.Solicitor5ImportId).Default("");
        Map(m => m.Solicitor5EverTrueId).Default("");
        Map(m => m.Solicitor5Name).Default("");
    }
}

When the Solicitor3 - 5 are not in the file it's returning null for their values. Will the .Default("") not work for this?


Solution

  • My understanding is that .Default() is for supplying a missing value, but what you have is a missing field.

    So if you wanted to replace empty fields with "NOVALUE" then .Default() is your guy. If you want to handle an entirely missing column, you'll need to modify the Configuration.MissingFieldFound setting and/or handle it by catching the exception.

    See: CsvHelper: Replace missing Csv field with another expression?

    and https://joshclose.github.io/CsvHelper/examples/configuration/

    Could you accomplish what you're after by simply setting the default value on your class attributes themselves? Just setting them to the empty string during construction?

    e.g.

    public string Solicitor3EverTrueId { get; set; } = "";