ajax 发布对象列表包含文件到 asp.net 控制器不起作用
Posted
技术标签:
【中文标题】ajax 发布对象列表包含文件到 asp.net 控制器不起作用【英文标题】:ajax post list of objects contains file to asp.net controller not working 【发布时间】:2021-09-17 05:36:39 【问题描述】:我正在研究 asp.net 核心,我想将包含来自 ajax 请求的文件的列表对象发送到控制器
这里有更多细节:在这张图片中,我要发送的对象包括文件
视图模型
public class FormDataVM
public Guid FormTemplateId get; set;
public int FieldTemplateId get; set;
public string Value get; set;
控制器
[HttpPost]
public async Task<JsonResult> SubmitForm(List<FormDataVM> formData , IFormFile file)
if (ModelState.IsValid)
var uploads = Path.Combine(_hostingEnvironment.WebRootPath, "images");
if (file != null && file.Length > 0)
var fileName = Guid.NewGuid().ToString().Replace("-", "") +
Path.GetExtension(file.FileName);
using (var s = new FileStream(Path.Combine(uploads, fileName),
FileMode.Create))
await file.CopyToAsync(s);
// to be continued
return Json(new status = "success", message = "success" );
return Json(new status = "failed", message = "failed" );
ajax 请求:data 是在控制台打印的对象
<form>
<div id="Cards">
@foreach (var item in Model.FieldTemplates)
<div class="form-box">
<div class="card">
<div class="card-body">
<h5 class="card-title">@item.Name</h5>
<div class="form-group">
@if (item.FieldTemplateEnum == FormBuilder.Enums.FieldTemplateEnum.Answer)
@html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<h5 class="card-title">
<input placeholder="Untitled Question" type="text" class="form-control AnswerInput">
</h5>
@if (item.FieldTemplateEnum == FormBuilder.Enums.FieldTemplateEnum.CheckBox)
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<div class="CheckBoxItemView">
@foreach (var value in item.FieldElementTemplates)
<div class="form-check">
<input class="form-check-input" name="CheckBoxInput" type="checkbox" value="@value.Value">
<label class="form-check-label" for="flexCheckDefault">
@value.Value
</label>
</div>
</div>
@if (item.FieldTemplateEnum == FormBuilder.Enums.FieldTemplateEnum.RadioButton)
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<div class="RadioButtonItemView">
@foreach (var value in item.FieldElementTemplates)
<div class="form-check">
<input class="form-check-input" type="radio" value="@value.Value" name="RadioInput" id="exampleRadios3">
<label class="form-check-label" for="exampleRadios3">
@value.Value
</label>
</div>
</div>
@if (item.FieldTemplateEnum == FormBuilder.Enums.FieldTemplateEnum.FileUpload)
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<div class="form-group">
<label for="exampleFormControlFile1">upload file</label>
<input type="file" class="form-control-file FileInput">
</div>
@if (item.FieldTemplateEnum == FormBuilder.Enums.FieldTemplateEnum.DateAndTime)
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<div class="col-md-4">
<input type="text" class="form-control DateTimeInput">
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" id="Submit" value="Submit" class="btn btn-primary" />
</div>
</div>
</div>
</div>
</form>
@section Scripts
<script type="text/javascript">
$(document).ready(function ()
$(function ()
$('.DateTimeInput').datetimepicker();
);
$('#Submit').click(function ()
PrepareForm();
);
function PrepareForm()
var DataObject = new Object();
var listCards = [];
$('#Cards>div').each(function ()
var singleObj = ;
singleObj['FormTemplateId'] = $('#Id').val();
singleObj['FieldTemplateId'] = $(this).find('#item_Id').val();
var templateType = $(this).find('#item_FieldTemplateEnum').val();
if (templateType == "Answer")
singleObj['Value'] = $(this).find('.AnswerInput').val();
else if (templateType == "CheckBox")
var selectedChecks = '';
$('input:checkbox[name=CheckBoxInput]:checked').each(function ()
selectedChecks += $(this).val() + " , ";
singleObj['Value'] = selectedChecks.replace(/,(\s+)?$/, '');
);
else if (templateType == "RadioButton")
singleObj['Value'] = $(this).find($("input[name=RadioInput]:checked")).val();
else if (templateType == "FileUpload")
singleObj['Value'] = $(this).find('.FileInput')[0].files[0];
//console.log($(this).find('.FileInput')[0].files[0].name);
else if (templateType == "DateAndTime")
singleObj['Value'] = $(this).find('.DateTimeInput').val();
listCards.push(singleObj);
);
DataObject = listCards;
console.log(DataObject);
var data = new FormData();
debugger;
for (var i = 0; i < DataObject.length; i++)
debugger;
data.append([i]+"FormTemplateId", DataObject[i].FormTemplateId);
data.append([i]+"FieldTemplateId", DataObject[i].FieldTemplateId);
data.append([i]+"Value", DataObject[i].Value);
SubmitForm(data);
function SubmitForm(formData)
$.ajax(
type: "POST",
url: "@Url.Action("SubmitForm", "Form")",
data: formData,
contentType: false,
processData: false,
success: function (message)
alert(message);
,
error: function ()
alert("there was error uploading files!");
);
);
</script>
当我发送请求时,实际操作中的列表始终计数为 0 并且文件为 null ,那么如何解决此问题。
【问题讨论】:
您的控制台屏幕截图显示data
是一个数组。此外,您必须使用 FormData 对象来上传文件。
【参考方案1】:
更新:
1.你没有任何id为Id
的元素,所以singleObj
中的FormTemplateId
是未定义的:
singleObj['FormTemplateId'] = $('#Id').val();
2.你需要把type="submit"
改成type="button"
:
<input type="button" id="Submit" value="Submit" class="btn btn-primary" />
3.需要添加名为file的FormData,因为后端接收文件参数为IFormFile file
:
data.append("file", $(this).find('.FileInput')[0].files[0]);
4.将包含按钮的div移到<div id="Cards">
之外,否则这里的代码($('#Cards>div').each
)会附加无用的值。
5.formdata包含值和键名,你的键名不正确,应该是[index].PropertyName
(例如[0].FormTemplateId
),你在下面所做的只是'indexPropertyName'(例如0FormTemplateId
):
data.append([i]+"FormTemplateId", DataObject[i].FormTemplateId);
data.append([i]+"FieldTemplateId", DataObject[i].FieldTemplateId);
data.append([i]+"Value", DataObject[i].Value);
您需要更改为:
data.append("["+i+"].FormTemplateId", DataObject[i].FormTemplateId);
data.append("[" + i +"].FieldTemplateId", DataObject[i].FieldTemplateId);
data.append("[" + i +"].Value", DataObject[i].Value);
这是一个完整的工作演示:
型号:
public class FormDataVM
public Guid FormTemplateId get; set;
public int FieldTemplateId get; set;
public string Value get; set;
public class FormTemplate
public List<FieldTemplate> FieldTemplates get; set;
public class FieldTemplate
public string FieldTemplateEnum get; set;
public string Name get; set;
public int Id get; set;
public List<FieldElementTemplate> FieldElementTemplates get; set;
public class FieldElementTemplate
public string Value get; set;
查看(不确定您的 html 中的 FormBuilder.Enums.FieldTemplateEnum.XXX
是什么。为了方便测试,我只是将其硬编码为一个简单的字符串):
@model FormTemplate
<form>
<div id="Cards">
@foreach (var item in Model.FieldTemplates)
<div class="form-box">
<div class="card">
<div class="card-body">
<h5 class="card-title">@item.Name</h5>
<div class="form-group">
@if (item.FieldTemplateEnum == "Answer")
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<h5 class="card-title">
<input placeholder="Untitled Question" type="text" class="form-control AnswerInput">
</h5>
@if (item.FieldTemplateEnum == "CheckBox")
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<div class="CheckBoxItemView">
@foreach (var value in item.FieldElementTemplates)
<div class="form-check">
<input class="form-check-input" name="CheckBoxInput" type="checkbox" value="@value.Value">
<label class="form-check-label" for="flexCheckDefault">
@value.Value
</label>
</div>
</div>
@if (item.FieldTemplateEnum == "RadioButton")
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<div class="RadioButtonItemView">
@foreach (var value in item.FieldElementTemplates)
<div class="form-check">
<input class="form-check-input" type="radio" value="@value.Value" name="RadioInput" id="exampleRadios3">
<label class="form-check-label" for="exampleRadios3">
@value.Value
</label>
</div>
</div>
@if (item.FieldTemplateEnum == "FileUpload")
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<div class="form-group">
<label for="exampleFormControlFile1">upload file</label>
<input type="file" class="form-control-file FileInput">
</div>
@if (item.FieldTemplateEnum == "DateAndTime")
@Html.HiddenFor(x => item.Id)
@Html.HiddenFor(x => item.FieldTemplateEnum)
<div class="col-md-4">
<input type="text" class="form-control DateTimeInput">
</div>
</div>
</div>
</div>
</div>
</div>
//move to here....
<div class="row">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
//change here....
<input type="button" id="Submit" value="Submit" class="btn btn-primary" />
</div>
</div>
</div>
</form>
JS:
$(document).ready(function ()
$(function ()
$('.DateTimeInput').datetimepicker();
);
$('#Submit').click(function ()
PrepareForm();
);
function PrepareForm()
var DataObject = new Object();
var listCards = [];
var data = new FormData(); //move to here...
$('#Cards>div').each(function ()
var singleObj = ;
//singleObj['FormTemplateId'] = $('#Id').val();
// you do not have element which id is Id in your html code...
//for easy testing...I hard coded a GUID...
singleObj['FormTemplateId'] = "2f1b0003-f8c9-47a5-ad2c-3ed2ace711d9";
singleObj['FieldTemplateId'] = $(this).find('#item_Id').val();;
var templateType = $(this).find('#item_FieldTemplateEnum').val();
if (templateType == "Answer")
singleObj['Value'] = $(this).find('.AnswerInput').val();
else if (templateType == "CheckBox")
var selectedChecks = '';
$('input:checkbox[name=CheckBoxInput]:checked').each(function ()
selectedChecks += $(this).val() + " , ";
singleObj['Value'] = selectedChecks.replace(/,(\s+)?$/, '');
);
else if (templateType == "RadioButton")
singleObj['Value'] = $(this).find($("input[name=RadioInput]:checked")).val();
else if (templateType == "FileUpload")
//add here..............
data.append("file", $(this).find('.FileInput')[0].files[0]);
singleObj['Value'] = $(this).find('.FileInput')[0].files[0];
else if (templateType == "DateAndTime")
singleObj['Value'] = $(this).find('.DateTimeInput').val();
listCards.push(singleObj);
);
DataObject = listCards;
console.log(DataObject);
debugger;
for (var i = 0; i < DataObject.length; i++)
debugger;
//change here.......
data.append("["+i+"].FormTemplateId", DataObject[i].FormTemplateId);
data.append("[" + i +"].FieldTemplateId", DataObject[i].FieldTemplateId);
data.append("[" + i +"].Value", DataObject[i].Value);
SubmitForm(data);
function SubmitForm(formData)
$.ajax(
type: "POST",
url: "@Url.Action("SubmitForm", "Home")",
data: formData,
contentType: false,
processData: false,
success: function (message)
alert(message);
,
error: function ()
alert("there was error uploading files!");
);
);
注意:我已在代码中为所有更改添加注释。请仔细阅读,不要遗漏任何内容。
结果:
【讨论】:
我试过你的例子,它是工作文件,但我的代码同样的问题,所以我会发布我的代码,你能帮我吗 嗨@Rena 有FormTemplate
模型,其中包含FieldTemplates
列表和foreach FieldTemplates 使用它的id `@Html.HiddenFor(x => 项进行隐藏输入。 Id)` 在运行时显示为<input data-val="true" data-val-required="The Id field is required." id="item_Id" name="item.Id" type="hidden" value="1">
嗨@KarimFahmy,您没有id="Id"
的任何元素。更多详细信息,您可以查看我更新的答案。如果对你有帮助,记得采纳为答案。
嗨@Rena,我在div.cards
上面有元素表单id,非常感谢以上是关于ajax 发布对象列表包含文件到 asp.net 控制器不起作用的主要内容,如果未能解决你的问题,请参考以下文章
对“asp.net core WebApi”的 ajax 调用返回一个奇怪/奇怪的值
带有大型数据源的 Kendo Chart 的 Ajax 请求上的 ASP.NET MVC 应用程序?
asp.net webforms ajax 更新gridview
在 ASP.Net Core 中使用 AJAX 将复选框列表类的值发送到服务器