在文件上传中使用CSVHelper

13

我正在尝试使用CSVhelper插件来读取上传的CSV文件。这是我的modelBinder类:

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();
        }
    }
}

这些是我想要映射的对象:

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; }

}

在Visual Studio调试器中,我遇到了一个错误:

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

2个回答

19

我没有使用这个插件,但错误信息似乎很明显。在访问结果之前必须调用 Read() 函数。尝试将你的代码更改为以下内容:

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();
}

糟糕!这就解决了问题 - 感谢您在我今天早上大脑还没完全清醒时的帮助。 - user547794
pate在编辑中删除了Read代码,我已经撤销了这个操作。请查看他的评论以了解他的原因。@pate,错误似乎很明显需要进行Read调用,所以请不要仅仅将其改回来。最好是添加您自己的新答案,因为您的编辑与我的答案的整个重点相矛盾。此外,OP确认此解决方案确实有效,因此您的编辑可能是错误的。 - Chris Snowden
2
@ChrisSnowden,你说得没错,需要调用Read()方法,但是GetRecords方法已经为你做了这个操作,参见源代码。在调用GetRecords()之前调用Read()会跳过第一条记录。也许你使用的是不同的版本? - Petrus Theron
@pate 正如我在回答中所说,我从未使用过这个插件,但错误提示需要在访问数据之前进行读取;OP确认这解决了问题。然而,也许它允许访问数据,但跳过了第一条记录。希望OP可以测试并验证这一点。如果不需要读取,则我猜测OP不会看到错误?你能否提出一个新的答案,显示OP需要对代码进行的更改?只是不想因此编辑而导致更多的踩。 - Chris Snowden

0
我曾经遇到过类似的问题,但是通过尝试下面的代码解决了。
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>();
    }
}

请注意,以下代码无法与最新版本的CSV Helper一起使用。
using (var csvReader = new CsvReader(reader))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接