ASP.NET MVC文件上传中用TempData解决校验失败表单数据清空问题
问题原因
你遇到表单数据清空的核心原因有两个:
- 文件格式校验失败后,你没有将用户已经提交的
PersonModel对象回传给视图,视图渲染时拿到的是空模型,自然不会填充之前填写的内容。 - 如果你在实际代码中校验失败后走了重定向逻辑,重定向本质是全新的GET请求,之前提交的表单上下文会全部丢失,也会导致内容清空。
解决步骤
1. 修改控制器逻辑
仅在上传成功时做重定向避免表单重复提交,校验失败时直接把用户提交的模型回传给视图即可保留原有内容,同时优化扩展名判断逻辑兼容大写后缀的情况:
[HttpPost] public ActionResult Index(PersonModel person, HttpPostedFileBase file) { if (file != null && file.ContentLength > 0) { var fileName = System.IO.Path.GetFileNameWithoutExtension(file.FileName); // 扩展名转小写,避免大写后缀(如.JPG)校验失败 var fileExtension = System.IO.Path.GetExtension(file.FileName).ToLower(); if (fileExtension == ".jpeg" || fileExtension == ".jpg" || fileExtension == ".gif" || fileExtension == ".png") { fileName = DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + fileName.Trim() + fileExtension; var userfolderpath = System.IO.Path.Combine(Server.MapPath("~/UploadedFiles/"), fileName); file.SaveAs(userfolderpath); TempData["Message"] = "Ok"; // 只有上传成功才重定向 return RedirectToAction("Index"); } else { // 用ViewBag存错误提示,不需要跨请求就不用TempData ViewBag.ErrorMsg = "请仅上传jpg、gif、png格式的图片文件"; } } // 校验失败直接回传用户提交的模型,保留表单内容 return View(person); }
2. 修改视图逻辑
确保视图顶部声明了正确的模型绑定,并且表单控件使用强类型绑定方法,校验失败后会自动填充原有内容:
<!-- 顶部必须声明绑定的模型 --> @model PersonModel @if (ViewBag.ErrorMsg != null) { <script type="text/javascript"> window.onload = function () { alert("@ViewBag.ErrorMsg.ToString()"); }; </script> } <!-- 表单用强类型绑定控件即可自动回填 --> @using (Html.BeginForm("Index", "你的控制器名", FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.LabelFor(m => m.姓名字段) @Html.TextBoxFor(m => m.姓名字段) @Html.ValidationMessageFor(m => m.姓名字段) <!-- 其他表单字段同理,都用强类型绑定控件 --> <input type="file" name="file" /> <button type="submit">提交</button> }
3. 可选优化(提升体验)
受浏览器安全策略限制,文件选择框的内容无法保留,用户校验失败后需要重新选择文件,其余普通表单字段都可以正常保留。
可以在前端加一层校验提前拦截不符合格式的文件,减少服务端校验的场景:
<!-- 给文件选择框加accept属性,限制用户默认只能选图片格式 --> <input type="file" name="file" accept=".jpg,.jpeg,.gif,.png" />
内容的提问来源于stack exchange,提问作者Edward Sheriff Curtis
相关产品推荐
相关产品推荐

