You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MVC Core学生数据验证及文件上传导出实现方案咨询

.NET MVC Core 学生数据验证与文件导出实现方案

核心实现流程

  1. 定义学生数据模型及验证规则
  2. 实现CSV文件解析与数据校验逻辑
  3. 生成有效/错误数据文件并提供下载
  4. 构建前端上传与结果展示界面

1. 模型定义(含验证规则)

使用数据注解实现基础字段校验,同时定义验证结果模型存储校验状态:

public class Student
{
    [Required(ErrorMessage = "学号不能为空")]
    [StringLength(20, ErrorMessage = "学号长度不能超过20位")]
    public string StudentId { get; set; }

    [Required(ErrorMessage = "姓名不能为空")]
    [StringLength(50, ErrorMessage = "姓名长度不能超过50位")]
    public string Name { get; set; }

    [Range(15, 30, ErrorMessage = "年龄必须在15-30之间")]
    public int Age { get; set; }

    [EmailAddress(ErrorMessage = "邮箱格式不正确")]
    public string Email { get; set; }
}

public class StudentValidationResult
{
    public Student ValidStudent { get; set; }
    public string ErrorMessage { get; set; }
    public bool IsValid => string.IsNullOrEmpty(ErrorMessage);
}

2. 数据处理服务

实现文件解析、校验、导出逻辑,依赖CsvHelper处理CSV文件(需安装NuGet包:Install-Package CsvHelper):

public interface IStudentDataService
{
    List<StudentValidationResult> ParseAndValidateFile(IFormFile file);
    byte[] GenerateValidStudentsCsv(List<StudentValidationResult> results);
    byte[] GenerateErrorStudentsCsv(List<StudentValidationResult> results);
}

public class StudentDataService : IStudentDataService
{
    public List<StudentValidationResult> ParseAndValidateFile(IFormFile file)
    {
        var results = new List<StudentValidationResult>();
        using var reader = new StreamReader(file.OpenReadStream());
        using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);

        var records = csv.GetRecords<Student>();
        foreach (var student in records)
        {
            var validationContext = new ValidationContext(student);
            var validationErrors = new List<ValidationResult>();
            var isValid = Validator.TryValidateObject(student, validationContext, validationErrors, validateAllProperties: true);

            results.Add(new StudentValidationResult
            {
                ValidStudent = student,
                ErrorMessage = isValid ? null : string.Join("; ", validationErrors.Select(e => e.ErrorMessage))
            });
        }
        return results;
    }

    public byte[] GenerateValidStudentsCsv(List<StudentValidationResult> results)
    {
        var validStudents = results.Where(r => r.IsValid).Select(r => r.ValidStudent).ToList();
        using var memoryStream = new MemoryStream();
        using var writer = new StreamWriter(memoryStream);
        using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);

        csv.WriteRecords(validStudents);
        writer.Flush();
        return memoryStream.ToArray();
    }

    public byte[] GenerateErrorStudentsCsv(List<StudentValidationResult> results)
    {
        var errorRecords = results.Where(r => !r.IsValid)
            .Select(r => new { r.ValidStudent.StudentId, r.ValidStudent.Name, r.ValidStudent.Age, r.ValidStudent.Email, r.ErrorMessage })
            .ToList();

        using var memoryStream = new MemoryStream();
        using var writer = new StreamWriter(memoryStream);
        using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture);

        csv.WriteRecords(errorRecords);
        writer.Flush();
        return memoryStream.ToArray();
    }
}

3. 控制器实现

处理文件上传、校验结果展示及文件下载请求:

public class StudentController : Controller
{
    private readonly IStudentDataService _studentDataService;

    public StudentController(IStudentDataService studentDataService)
    {
        _studentDataService = studentDataService;
    }

    public IActionResult Index() => View();

    [HttpPost]
    public IActionResult Upload(IFormFile file)
    {
        if (file == null || file.Length == 0)
        {
            ModelState.AddModelError("file", "请选择要上传的文件");
            return View("Index");
        }

        if (!file.FileName.EndsWith(".csv", StringComparison.OrdinalIgnoreCase))
        {
            ModelState.AddModelError("file", "仅支持CSV格式文件");
            return View("Index");
        }

        var validationResults = _studentDataService.ParseAndValidateFile(file);
        TempData["ValidCount"] = validationResults.Count(r => r.IsValid);
        TempData["ErrorCount"] = validationResults.Count(r => !r.IsValid);
        TempData["ValidationResults"] = validationResults;

        return RedirectToAction("Result");
    }

    public IActionResult Result()
    {
        if (TempData["ValidationResults"] == null) return RedirectToAction("Index");
        ViewBag.ValidCount = TempData["ValidCount"];
        ViewBag.ErrorCount = TempData["ErrorCount"];
        return View();
    }

    public IActionResult DownloadValidData()
    {
        var results = TempData.Peek("ValidationResults") as List<StudentValidationResult>;
        if (results == null) return NotFound();

        var csvBytes = _studentDataService.GenerateValidStudentsCsv(results);
        return File(csvBytes, "text/csv", $"有效学生数据_{DateTime.Now:yyyyMMddHHmmss}.csv");
    }

    public IActionResult DownloadErrorData()
    {
        var results = TempData.Peek("ValidationResults") as List<StudentValidationResult>;
        if (results == null) return NotFound();

        var csvBytes = _studentDataService.GenerateErrorStudentsCsv(results);
        return File(csvBytes, "text/csv", $"错误学生数据_{DateTime.Now:yyyyMMddHHmmss}.csv");
    }
}

4. 前端UI实现

上传页面(Index.cshtml)

@{ ViewData["Title"] = "学生数据上传验证"; }
<h1>学生数据上传验证</h1>

<form method="post" enctype="multipart/form-data">
    <div class="mb-3">
        <label for="file" class="form-label">选择CSV文件</label>
        <input type="file" class="form-control" id="file" name="file" accept=".csv">
        @if (!ModelState.IsValid)
        {
            <span class="text-danger">@ModelState["file"].Errors.First().ErrorMessage</span>
        }
    </div>
    <button type="submit" class="btn btn-primary">上传并验证</button>
</form>

结果页面(Result.cshtml)

@{ ViewData["Title"] = "验证结果"; }
<h1>验证结果</h1>

<div class="alert alert-info">
    有效数据: @ViewBag.ValidCount 条 | 错误数据: @ViewBag.ErrorCount 条
</div>

@if (ViewBag.ValidCount > 0)
{
    <a href="@Url.Action("DownloadValidData")" class="btn btn-success me-2">下载有效数据</a>
}

@if (ViewBag.ErrorCount > 0)
{
    <a href="@Url.Action("DownloadErrorData")" class="btn btn-danger">下载错误数据</a>
}

<p><a href="@Url.Action("Index")" class="btn btn-secondary">返回上传页面</a></p>

5. 服务注册

在Program.cs中注册数据处理服务:

builder.Services.AddScoped<IStudentDataService, StudentDataService>();
builder.Services.AddControllersWithViews();

关键注意事项

  • CSV文件表头需与Student模型属性名完全匹配(如StudentId, Name, Age, Email)
  • 如需支持Excel文件,可替换CsvHelper为EPPlus库实现
  • 大文件场景建议采用流式处理避免内存溢出
  • 可扩展添加自定义校验规则(如学号唯一性检查,需结合数据库查询)

内容的提问来源于stack exchange,提问作者Radha Kadam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 08:30:55