ASP.NET MVC5中HttpPostedFileBase始终返回null的问题排查
我正在ASP.NET MVC5应用中实现文件上传功能,已经编写了cshtml视图、ViewModel和Mvc Action代码,但提交表单时HttpPostedFileBase类型的FileNew始终返回null,麻烦帮忙看看哪里出错了?
我的代码:
视图(cshtml):
<form action="@Url.Action("send-message", "users", new { area = "security" })" class="form-horizontal" method="POST" data-async data-target="#send-message-modal" enctype="multipart/form-data"> <div class="row"> <div class="col-md-12"> @Html.TextBoxFor(m => m.Email, new { placeholder = "Select the recipient...", @class = "form-control form-group-margin" }) @Html.HiddenFor(m => m.RecipientId) </div> </div> @Html.TextBoxFor(m => m.Title, new { placeholder = "Enter a subject", @class = "form-control" }) @Html.ValidationMessageFor(m => m.Title) @Html.TextAreaFor(m => m.Message, new { placeholder = "Enter your message", @class = "form-control", rows = 5 }) @Html.ValidationMessageFor(m => m.Message) @Html.TextBoxFor(m => m.FileNew, new { type = "file", @class = "form-control", name= "FileNew" }) <br/> @Html.ValidationMessageFor(m => m.FileNew) <div class="panel-footer text-right no-padding-hr no-padding-b"> <button class="btn btn-primary">Send message</button> </div> </form>
ViewModel:
public class SendMessageModel { [Display(Name = "Recipient")] [DataType(DataType.EmailAddress)] [StringLength(255)] public string Email { get; set; } [Required] [Display(Name = "Recipient")] public int RecipientId { get; set; } [DataType(DataType.Text)] [Required] [Display(Name = "Message")] public string Message { get; set; } public bool IsSent { get; set; } [DataType(DataType.Text)] [Required] [Display(Name = "Subject")] public string Title { get; set; } public HttpPostedFileBase FileNew { get; set; } }
MVC Action:
[ActionName("send-message")] [HttpPost] public ActionResult SendMessage(SendMessageModel model) { }
问题排查与解决办法:
我帮你梳理了几个可能导致HttpPostedFileBase为null的原因,你可以逐一排查:
异步提交的表单数据处理问题
你给表单加了data-async属性,说明是异步提交。普通的jQuery异步提交默认不会处理multipart/form-data编码的表单,这会直接导致文件无法传递到后台。如果要保留异步提交,需要用FormData对象封装表单数据:$('form').submit(function(e) { e.preventDefault(); var formData = new FormData(this); $.ajax({ url: $(this).attr('action'), type: 'POST', data: formData, processData: false, // 必须设置为false,否则jQuery会自动处理数据,破坏FormData结构 contentType: false, // 必须设置为false,让浏览器自动生成正确的Content-Type success: function(result) { // 这里处理成功回调逻辑 } }); });如果不需要异步提交,直接去掉
data-async属性,让表单以普通方式提交即可,此时enctype="multipart/form-data"会正常生效。确认文件输入框的名称匹配
你手动指定了name= "FileNew",虽然TextBoxFor会自动生成和属性名一致的name,但还是建议检查渲染后的HTML中input的name是否确实是FileNew(注意大小写敏感,必须和ViewModel的属性名完全一致)。检查文件大小限制
ASP.NET默认限制上传文件大小为4MB,如果你的文件超过这个值,也会导致HttpPostedFileBase为null。可以在Web.config中调整配置:<system.web> <!-- maxRequestLength单位是KB,这里设置为1GB --> <httpRuntime maxRequestLength="1048576" /> </system.web> <!-- IIS7及以上需要额外配置 --> <system.webServer> <security> <requestFiltering> <!-- maxAllowedContentLength单位是字节,这里设置为1GB --> <requestLimits maxAllowedContentLength="1073741824" /> </requestFiltering> </security> </system.webServer>排查模型绑定问题
可以尝试在Action中直接接收HttpPostedFileBase参数,测试是否能获取到文件,以此区分是表单提交问题还是模型绑定问题:[ActionName("send-message")] [HttpPost] public ActionResult SendMessage(SendMessageModel model, HttpPostedFileBase FileNew) { }
按照上面的步骤逐一排查,应该就能解决HttpPostedFileBase为null的问题了。
内容的提问来源于stack exchange,提问作者user740022

