MVC Web API项目使用jQuery AJAX上传图片Controller接收参数为null如何解决
问题排查与解决方案
核心错误原因
你当前的请求配置存在三处本质错误,导致文件无法被后端正确识别:
- JSON 格式不支持传输二进制文件对象,将
File实例放入普通对象序列化后只会得到空值,后端自然无法接收到文件 - AJAX配置中同时设置了
contentType: "application/json"和enctype: 'multipart/form-data',二者完全冲突,实际请求只会按JSON格式提交,文件不会被传输 - 你赋值的
$('.picture')[0].files是文件列表数组,需要取第一个元素才是对应上传的单个文件对象
具体修改方案
1. 前端AJAX代码修改
全部改用FormData承载提交数据,同时调整AJAX配置:
// 此处替换你原有的点击事件代码 $('.empOfficialDetails').click(function (ev) { ev.preventDefault(); // 使用FormData承载所有表单和文件数据 var formData = new FormData(); formData.append('UserName', $('#username').val()); formData.append('UPassword', $('#userpass').val()); formData.append('OfficialEmailAddress', $('#officialemail').val()); formData.append('Departments', $('#departments :selected').text()); formData.append('Designation', $('#designation :selected').text()); formData.append('RoleID', $('#role').val()); formData.append('Role', $('#role :selected').text()); formData.append('ReportToID', $('#reportToID').val()); formData.append('ReportTo', $('#reportTo :selected').text()); formData.append('JoiningDate', $('#joindate').val()); formData.append('IsAdmin', $('#isAdmin :selected').val() ? 1 : 0); formData.append('IsActive', $('#isActive :selected').val() ? 1 : 0); formData.append('IsPermanent', $('#isPermanent :selected').val() ? 1 : 0); formData.append('DateofPermanancy', $('#permanantdate').val()); formData.append('HiredbyReference', $('#hiredbyRef :selected').val() ? 1 : 0); formData.append('HiredbyReferenceName', $('#refePersonName').val()); formData.append('BasicSalary', $('#basicSalary').val()); // 取文件列表的第一个元素作为上传文件 formData.append('CurrentPicURL', $('.picture')[0].files[0]); if (formData.get('UserName') && formData.get('UPassword') && formData.get('OfficialEmailAddress') && formData.get('Departments') && formData.get('Designation') && formData.get('Role') && formData.get('IsAdmin') && formData.get('IsPermanent')) { $.ajax({ url: 'http://localhost:1089/api/Employee/EmpOfficialDetails', type: "POST", dataType: 'json', // 关键配置:禁止jQuery处理FormData,禁止自动设置请求类型 processData: false, contentType: false, data: formData, beforeSend: function () { $("#dvRoomsLoader").show(); }, complete: function () { $("#dvRoomsLoader").hide(); }, success: function (data) { var ID = parseInt(data); if (ID > 0) { $(".HiddenID").val(data); $('#official').css('display', 'block'); $('#official').html("Employees Official details added successfully...!"); $('#official').fadeOut(25000); $("#dvRoomsLoader").show(); $('.empOfficialDetails').html("Update <i class='fa fa-angle-right rotate-icon'></i>"); } else { $('#official').find("alert alert-success").addClass("alert alert-danger").remove("alert alert-success"); } }, error: function (ex) { alert("There was an error while submitting employee data"); alert('Error' + ex.responseXML); alert('Error' + ex.responseText); alert('Error' + ex.responseJSON); alert('Error' + ex.readyState); alert('Error' + ex.statusText); } }); } return false; });
2. 后端代码优化
建议在调用文件保存方法前增加非空判断,避免未上传文件时抛出空引用异常:
public int Emp_OfficialDetails(Employee emp) { var con = DB.getDatabaseConnection(); SqlCommand com = new SqlCommand("sp_InsEmpOfficialDetails", con); com.CommandType = CommandType.StoredProcedure; #region Employee Official Details Insert Code block com.Parameters.AddWithValue("@UserName", emp.UserName); com.Parameters.AddWithValue("@pass", emp.UPassword); com.Parameters.AddWithValue("@OfficialEmailAddress", emp.OfficialEmailAddress); com.Parameters.AddWithValue("@Department", emp.Departments); com.Parameters.AddWithValue("@Role", emp.Role); com.Parameters.AddWithValue("@IsAdmin", Convert.ToBoolean(emp.IsAdmin)); com.Parameters.AddWithValue("@Designation", emp.Designation); com.Parameters.AddWithValue("@ReportToID", emp.ReportToID); com.Parameters.AddWithValue("@ReportTo", emp.ReportTo); com.Parameters.AddWithValue("@JoiningDate", Convert.ToDateTime(emp.JoiningDate)); com.Parameters.AddWithValue("@IsPermanent", Convert.ToBoolean(emp.IsPermanent)); com.Parameters.AddWithValue("@DateofPermanancy", Convert.ToDateTime(emp.DateofPermanancy)); com.Parameters.AddWithValue("@IsActive", Convert.ToBoolean(emp.IsActive)); com.Parameters.AddWithValue("@HiredbyReference", Convert.ToBoolean(emp.HiredbyReference)); com.Parameters.AddWithValue("@HiredbyReferenceName", emp.HiredbyReferenceName); com.Parameters.AddWithValue("@BasicSalary", emp.BasicSalary); com.Parameters.AddWithValue("@CurrentPicURL", emp.CurrentPicURL?.FileName ?? ""); #endregion // 增加非空判断 if (emp.CurrentPicURL != null && emp.CurrentPicURL.ContentLength > 0) { EmployeeImage(emp.CurrentPicURL); } var ID = com.ExecuteScalar(); com.Clone(); return Convert.ToInt32(ID); }
额外检查项
- 确认控制器的
Emp_OfficialDetails方法已添加[HttpPost]特性 - 确认Web API路由配置可正常映射到该方法
- 确认前端文件输入框没有设置
disabled属性,可正常选择文件
内容的提问来源于stack exchange,提问作者Syed Muhammad Aousaja Ali
相关产品推荐
相关产品推荐

