javascript - ajax 发布对象列表包含文件到 asp.net 控制器不起作用
问题描述
我正在研究 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请求:数据是控制台打印的对象
<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 ,那么如何解决此问题。
解决方案
更新:
1.您没有任何 id 为Id
的元素,因此FormTemplateId
insingleObj
未定义:
singleObj['FormTemplateId'] = $('#Id').val();
2.您需要更改type="submit"
为type="button"
:
<input type="button" id="Submit" value="Submit" class="btn btn-primary" />
3.您需要添加名称为文件的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; }
}
查看(不确定FormBuilder.Enums.FieldTemplateEnum.XXX
您的 html 中有什么。为了方便测试,我只是将其硬编码为一个简单的字符串):
@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!");
}
});
}
});
注意:我在代码中为所有更改添加了注释。请仔细阅读,不要遗漏任何内容。
结果:
推荐阅读
- forms - 是否可以在移动键盘上访问/显示取消按钮?
- apollo-android - 构建 Android ApolloClient 时无法指定 wss URL
- python - 如何对 bitbucket 云 API 进行身份验证,然后在身份验证后使用它们?
- java - 从多个地方在 JPanel 上绘图
- php - Laravel 数据透视表 - 保存来自其他列的数据
- java - 无效或有问题的 jar 文件
- swift - 尽管 zPosition = 1,但无法强制子视图位于最前面
- python - 使用 Chrome 驱动程序时出错 - 未捕获的 ReferenceError:未定义 showDate
- java - 将 java 代理添加到 wildfly10.1.Final 服务器
- python - 总结熊猫数据框中的某些行组