I need to write a HttpPostedFileBase
csv (and save it) after mapping it into a list using the CsvHelper nuget package. However, after mapping it with CsvHelper, the ContentLength
is 0, and I end up saving an empty .csv file.
CsvHelper itself states that the Read method should not be used when using the GetRecords<T>()
method.
// Summary:
// Gets all the records in the CSV file and converts each to System.Type T. The
// Read method should not be used when using this.
//
// Type parameters:
// T:
// The System.Type of the record.
//
// Returns:
// An System.Collections.Generic.IEnumerable`1 of records.
public virtual IEnumerable<T> GetRecords<T>();
I tried placing it into a copy variable:
HttpPostedFileBase csvCopy = csvFile;
But this didn't work. Tried some other solutions I found on stackoverflow, which didn't work either. I "solved" this problem by sending the same file twice to the controller as a parameter. Then I use the first one with CsvHelper, and I read and save the other one.
public async Task<ActionResult> ImportCSV(HttpPostedFileBase csvFile, HttpPostedFileBase csvFileCopy)
However, I think this is a bad solution. I would like to use a single file, map it, reread it and save it.
Mapping it into a list:
using(var reader = new StreamReader(csvFile.InputStream)) {
using(var csvReader = new CsvReader(reader)) {
csvReader.Configuration.RegisterClassMap(new CSVModelMap(mapDictionary));
csvReader.Configuration.BadDataFound = null;
csvReader.Configuration.HeaderValidated = null;
csvReader.Configuration.MissingFieldFound = null;
importData = csvReader.GetRecords<CSVModel>().ToList();
}
}
Saving it:
var fileName = serverPath + "\\" + hashedFileName;
CheckIfDirectoryExists(serverPath);
var reader = new StreamReader(csvFile.InputStream);
var csvContent = await reader.ReadToEndAsync();
File.WriteAllText(fileName, csvContent);
The issue was CsvHelper:
using(var csvReader = new CsvReader(reader))
At the end of the using statement, CsvReader
closes the reader. Then when I try
csvFile.InputStream.Seek(0, SeekOrigin.Begin);
or
reader.BaseStream.Position = 0;
it throws a NullReferenceException
. I solved this by simply overriding the CsvReader
:
using (var csvReader = new CsvReader(reader, true))
true
being leaveOpen
:
// Summary:
// Creates a new CSV reader using the given System.IO.TextReader.
//
// Parameters:
// reader:
// The reader.
//
// leaveOpen:
// true to leave the reader open after the CsvReader object is disposed, otherwise
// false.
public CsvReader(TextReader reader, bool leaveOpen);
Then I set the position back to 0, using reader.BaseStream.Position = 0;
, and then after saving the file, dispose the reader.