'CsvHelper "TypeConverterException: Converting IEnumerable types is not supported for a single field."
I am trying to build a simple csv of user data from a list i have retrieved form my database. When i run the code i get a crash on the csv.WriteRecods(data) that reads "TypeConverterException: Converting IEnumerable types is not supported for a single field."
var mem = new MemoryStream();
var writer = new StreamWriter(mem);
var csv = new CsvWriter(writer, CultureInfo.CurrentUICulture);
var data = myList.Select(x =>
{
dynamic item = new ExpandoObject();
var dict = item as IDictionary<string, object>;
dict["DisplayName"] = x.User.DisplayName;
dict["Email"] = x.User.Email;
return dict;
}).ToList();
csv.WriteRecords(data);
writer.Flush();
mem.Seek(0, SeekOrigin.Begin);
return File(mem, "text/csv", $"Test_{DateTime.Now.ToString("yyyy-MM-dd_HHmmss")}.csv");
In the past i have used the CsvHelper v12 nuget package for Net Core in VS and have never had this issue. I am only finding this issue int he newer V15 but because of other parts of the application using the package i can not downgrade to v12.
Solution 1:[1]
So out of curiosity I wanted to see what was going on. I started a new project and copy and pasted your code. I couldn't get it to work on either v15 or v12 as-is. It was throwing the same exception in both versions.
So I started researching it. From what I can tell CsvHelper doesn't really support dictionaries. But from what I can see, you shouldn't need to do it the way you are doing it. You can create "Mapper" object that can pull specific information from the models you want to serialize:
public class TestModelWithUserMap : ClassMap<TestModelWithUser>
{
public TestModelWithUserMap()
{
Map(m => m.User.DisplayName);
Map(m => m.User.Email);
}
}
private static void TestCsvHelper()
{
// generate some random data
var rnd = new Random();
var lst = Enumerable.Range(0, 50).Select(x => new TestModelWithUser
{
User = new UserModel
{
DisplayName = new string(Enumerable.Range(0, 20).Select(_ => Convert.ToChar(rnd.Next(0x61, 0x7b))).ToArray()),
Email = new string(Enumerable.Range(0, 15).Select(_ => Convert.ToChar(rnd.Next(0x61, 0x7b))).ToArray())
}
});
// open file and begin to write
using (var fs = File.OpenWrite(@"c:\users\andy\desktop\test.csv"))
using (var sr = new StreamWriter(fs))
using (var csv = new CsvWriter(sr))
{
// register our mapper
csv.Configuration.RegisterClassMap(new TestModelWithUserMap());
// write all records
csv.WriteRecords(lst);
}
}
The output of the file looks like this:
This way seems a lot more efficient and maintainable as you don't have to deal with dynamic/ExpandoObjects.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Andy |

