13

I am trying to use the CSVhelper plugin to read an uploaded CSV file. Here is my modelBinder class:

public class SurveyEmailListModelsModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var csv = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        var file = ((csv.RawValue as HttpPostedFileBase[]) ?? Enumerable.Empty<HttpPostedFileBase>()).FirstOrDefault();

        if (file == null || file.ContentLength < 1)
        {
            bindingContext.ModelState.AddModelError(
                "",
                "Please select a valid CSV file"
            );
            return null;
        }

        using (var reader = new StreamReader(file.InputStream))
        using (var csvReader = new CsvReader(reader))
        {
            return csvReader.GetRecords<SurveyEmailListModels>().ToArray();
        }
    }
}

These are the objects I am trying to map to:

public class SurveyEmailListModels
{
    [Key]
    [CsvField(Ignore = true)]
    public int SurveyEmailListId { get; set; }

    [CsvField(Index = 0)]
    public int ProgramId { get; set; }

    [CsvField(Index = 1)]
    public virtual SurveyProgramModels SurveyProgramModels { get; set; }

    [CsvField(Index = 2)]
    public string SurveyEmailAddress { get; set; }

    [CsvField(Index = 3)]
    public bool SurveyResponded { get; set; }

}

Inside the Visual Studio debugger I am getting an error:

  • base {"You must call read on the reader before accessing its data."} CsvHelper.CsvHelperException {CsvHelper.CsvReaderException}

Erik Schierboom
  • 16,301
  • 10
  • 64
  • 81
user547794
  • 14,263
  • 36
  • 103
  • 152

2 Answers2

19

Not used the plugin but the error message seems pretty clear. There must be a Read() function to call before accessing the results. Try changing your code to something like this:

using (var reader = new StreamReader(file.InputStream))
using (var csvReader = new CsvReader(reader))
{
    // Use While(csvReader.Read()); if you want to read all the rows in the records)
    csvReader.Read();
    return csvReader.GetRecords<SurveyEmailListModels>().ToArray();
}
Anirudha Gupta
  • 9,073
  • 9
  • 54
  • 79
Chris Snowden
  • 4,982
  • 1
  • 25
  • 34
  • Doh! That did the trick - thanks for helping out while my brain gets up to speed this morning. – user547794 Jun 18 '12 at 16:29
  • The Read code was removed in an edit by pate which I have undone for now. Please see his comments for his reason for this. @pate the error seems pretty clear that a Read call needs to be made so don't just change this back please. Ideally add your own new answer instead since your edit contradicts the whole point of my answer. Also the OP confirmed that this solution did in fact work so you may be wrong about your edit. – Chris Snowden Jul 30 '14 at 08:16
  • 2
    @ChrisSnowden you're right about a `Read()` call being required, but the `GetRecords` method does this for you, as per [the source](https://github.com/JoshClose/CsvHelper/blob/master/src/CsvHelper/CsvReader.cs#L916). Calling `Read()` before GetRecords() will skip the first records. Perhaps you have a different version? – Petrus Theron Jul 30 '14 at 08:26
  • @pate As I said in my answer I've never used the plugin but the error suggested that a Read was required before accessing the data; the OP confirmed that this solved the problem. However, maybe it allowed accessing the data but skipped the first record(s). Hopefully the OP can test and verify this. If the Read wasn't required then I'd guess the OP would have not seen the error? Could you suggest a new answer that shows the change the OP needs to make to his code? Just don't want any more downvotes as a result of this edit if possible as you changed the code to contradict my explanation. – Chris Snowden Jul 30 '14 at 08:39
0

I had similar issue , but sorted out, when I tried the below code

void Main()
{
    using (var reader = new StreamReader("path\\to\\file.csv"))
    using (var csv = new CsvReader(reader, 
           System.Globalization.CultureInfo.CreateSpecificCulture("enUS")))
    {
        var records = csv.GetRecords<Foo>();
    }
}

Please note below code wont work with latest versions of CSV Helper

using (var csvReader = new CsvReader(reader))
jithin john
  • 552
  • 4
  • 12