首页 > 解决方案 > 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 ,那么如何解决此问题。

标签: javascriptc#jqueryajaxasp.net-core

解决方案


更新:

1.您没有任何 id 为Id的元素,因此FormTemplateIdinsingleObj未定义:

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!");
            }
        });
    }
});

注意:我在代码中为所有更改添加了注释。请仔细阅读,不要遗漏任何内容。

结果: 在此处输入图像描述


推荐阅读