using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using CsvHelper.Configuration;
using CsvHelper.Configuration.Attributes;
using CsvHelper.Expressions;
using CsvHelper.TypeConversion;
public int? Count { get; set; }
public string CustomerName { get; set; }
public string CustomerAddress { get; set; }
public class VisitMap : ClassMap<VisitExport>
Map(m => m.Count).Name("Count");
Map(m => m.CustomerName).Name("Customer Name");
Map(m => m.CustomerAddress).Name("Customer Address");
public class VisitMapBackwards : ClassMap<VisitExport>
public VisitMapBackwards()
Map(m => m.CustomerAddress).Name("Customer Address");
Map(m => m.CustomerName).Name("Customer Name");
Map(m => m.Count).Name("Count");
public static void Test()
var inputList = new List<VisitExport>
new VisitExport { Count = 101, CustomerName = "name 101", CustomerAddress = "customer address 101" },
new VisitExport { Count = null, CustomerName = "name 1", CustomerAddress = "customer address 1" },
new VisitExport { Count = 202, CustomerName = "name 202", CustomerAddress = "customer address 202" },
var json0 = JsonConvert.SerializeObject(inputList);
var csv1 = TestOutput(inputList, new VisitMap());
Console.WriteLine("CSV export for model:");
var csv1Lower = csv1.ToLowerInvariant();
var csv2 = TestOutput(inputList, new VisitMapBackwards());
var newList1 = TestInput(csv1, new VisitMap());
var newList2 = TestInput(csv2, new VisitMap());
var newList11 = TestInput(csv1Lower, new VisitMap(), (args) => args.Header.ToLowerInvariant());
Console.WriteLine("Caught expected exception: {0}",
Assert.Throws<HeaderValidationException>(() =>
TestInput(GetMissingColumnCsv(), new VisitMap());
Console.WriteLine("Caught expected exception: {0}",
Assert.Throws<HeaderValidationException>(() =>
TestInput(GetMissingColumnCsv().ToLowerInvariant(), new VisitMap(), (args) => args.Header.ToLowerInvariant());
var json1 = JsonConvert.SerializeObject(newList1);
var json11 = JsonConvert.SerializeObject(newList11);
var json2 = JsonConvert.SerializeObject(newList2);
Assert.AreEqual(json0, json1);
Assert.AreEqual(json0, json11);
Assert.AreEqual(json0, json2);
public static List<VisitExport> TestInput(string csv, ClassMap<VisitExport> map, PrepareHeaderForMatch prepareHeaderForMatch = default)
var culture = CultureInfo.GetCultureInfo("en-GB");
var config = new CsvConfiguration (culture)
HeaderValidated = (args) =>
ConfigurationFunctions.HeaderValidated(args);
if (prepareHeaderForMatch != null)
config.PrepareHeaderForMatch = prepareHeaderForMatch;
using (var reader = new StringReader(csv))
using (var readCsv = new CsvReader(reader, config))
readCsv.Context.RegisterClassMap(map);
var fileContent = readCsv.GetRecords<VisitExport>();
return fileContent.ToList();
public static string TestOutput(List<VisitExport> inputList, ClassMap<VisitExport> map)
var culture = CultureInfo.GetCultureInfo("en-GB");
var config = new CsvConfiguration (culture);
var sb = new StringBuilder();
using (var textWriter = new StringWriter(sb))
using (var csvWriter = new CsvWriter(textWriter, config))
csvWriter.Context.RegisterClassMap(map);
csvWriter.WriteRecords(inputList);
static string GetMissingColumnCsv() => @"Customer Name,Count
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("CsvHelper: " + typeof(CsvConfiguration).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];