8

我正在尝试将图像上传到我的应用程序,但它总是返回 null。我在这里找不到问题。你能帮我吗?这是我的代码。

模型


[Table("Slider")]
public partial class Slider : BaseModel
{
    [Required]
    [StringLength(200)]
    public string FileName { get; set; }

    [StringLength(200)]
    public string Title { get; set; }

    [StringLength(1000)]
    public string Description { get; set; }

    public int? Order { get; set; }
}


[NotMapped]
public class SliderImage : Slider
{
    public HttpPostedFileBase ImageFile { get; set; }
}

看法


@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<div class="modal-body">
    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.FileName, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.FileName, new { @class = "form-control", @readonly = "readonly" })
                @Html.ValidationMessageFor(model => model.FileName, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.ImageFile, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.ImageFile, new { @class = "form-control", type = "file" })
               //This is Same as below
               //<input class="form-control" id="ImageFile" name="ImageFile" type="file" value="">
            </div>
        </div>

控制器


    public ActionResult Edit(int id)
    {
        Slider slider = _db.Sliders.Find(id);
        if (slider == null)
        {
            return HttpNotFound();
        }
        Mapper.CreateMap<Slider, SliderImage>();
        SliderImage sliderImage = Mapper.Map<Slider, SliderImage>(slider);
        return PartialView("_Edit", sliderImage);
    }


    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult EditSlider([Bind(Include = "Id,FileName,Title,Description,Order,IsActive,Name,ImageFile")] SliderImage sliderImage)
    {
        if (ModelState.IsValid)
        {
            Mapper.CreateMap<SliderImage, Slider>();
            Slider slider = Mapper.Map<SliderImage, Slider>(sliderImage);
            _db.Entry(slider).State = EntityState.Modified;
            _db.SaveChanges();
            return Json(new { success = true });
        }
        return PartialView("_EditSlider");
    }

我做错了什么?


发现问题

我在引导模式弹出窗口中绑定部分视图。当我从弹出窗口上传时,上传返回 null。相反,如果我直接在浏览器中打开部分视图,则该文件存在于模型中。所以文件上传没有问题。问题出在模态弹出窗口之类的东西上。

使用 Bootstrap 模型时 使用 Bootstrap 模型时

使用部分 View Directy 时 使用部分 View Directy 时

分别查看下图中Bootstrap Modal Submit和Using the partial View Directly使用fiddler时发现的区别

Fiddler 请求比较

从模式弹出窗口发布时,内容类型更改为application/x-www-form-urlencoded直接使用局部视图时的位置multipart/form-data


找到了根本问题。

$('form', dialog).submit(function () {
                    var $form = $(this);
                    var enctype = $form.attr('id');
                    $.ajax({
                        url: this.action,
                        type: this.method,
                        data: $(this).serialize(),
                        success: function (result) {
                            if (result.success) {
                                $('#myModal').modal('hide');
                                //Refresh
                                location.reload();
                            } else {
                                $('#myModalContent').html(result);
                                bindForm();
                            }
                        }
                    });
                    return false;
                });

我正在使用 AJAX 发布从我的表单提交数据。使用$(this).serialize()ajax 时成功调用但文件没有返回,因为内容类型不同。我怎样才能改变这个?

4

6 回答 6

2

我想我已经能够确定你的问题了,Ajax 不支持文件序列化,你应该在脚本中使用以下方法:

$('form', dialog).submit(function () {
        var formData = new FormData($(this)[0]);
        $.ajax({
            url: this.action,
            type: this.method,
            contentType: this.enctype,
            data: formData,
            success: function (result) {
                if (result.success) {
                    $('#myModal').modal('hide');
                    $('#replacetarget').load(result.url); //  Load data from the server and place the returned HTML into the matched element
                } else {
                    $('#myModalContent').html(result);
                    bindForm(dialog);
                }
            }
        });
        return false;
    });
于 2016-11-30T10:45:08.817 回答
1

好的,我认为您当前的问题与 jQuery.ajax 方法的默认设置有关。默认情况下,jQuery.ajax() 方法的内容类型是'application/x-www-form-urlencoded; charset=UTF-8'. 因此,在一个示例项目中,我修改了您的 javascript 函数以将 contentType 指定为 ajax 方法的参数:contentType: this.enctype

我认为可能还有一些额外的问题。我注意到的下一个问题是,在提交时,我正在连接到另一个操作,因此我在视图中更新了这一行:

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))

对此:

@using (Html.BeginForm("EditSlider", "<Your Controller Name>", FormMethod.Post, new { enctype = "multipart/form-data" }))

最后,当 ajax 提交时,我被重定向到部分视图。我相信这可以通过将 preventDefault 添加到 ajax 函数来解决:

$('form', dialog).submit(function (event) {
    event.preventDefault();
    var $form = $(this);
    $.ajax({
        url: this.action,
        type: this.method,
        contentType: this.enctype,
        data: $(this).serialize(),
        success: function (result) {
            if (result.success) {
                $('#myModal').modal('hide');
                //Refresh
                location.reload();
            } else {
                $('#myModalContent').html(result);
                bindForm();
            }
        }
    });
});

这就是我如何让这个例子在一个示例项目中工作;如果您有其他问题,请发布更新。

于 2014-11-03T17:56:06.303 回答
0

只有上传的文件返回null?还是其他文本框也返回 null ?正如@Andrei 评论的那样,通常模态被移动到一个新位置并且表单不存在,或者您的部分视图可以移动以使模态工作。

使用 jqueryUI 我遇到了类似的问题。如果您使用 ajax 提交数据,我在您的问题中找不到,您可以使用 .ajax() 发送表单并查看图像是否已上传

$.ajax({
            url: "@Url.Action("Action", "Controller")",
            type: "POST",
            cache: false,
            data: $("#YourFormID").serialize(),
            success: function (result) {
               //your success data

            },
            error: function (jqXHR, textStatus, errorThrown) {
               //your error handler
            },
        });

         return false;

如果您不想使用 $.ajax(),您可以尝试将 .appendTo() 与 jquery 一起使用,将表单内的所有内容包装在带有 ID 的 div 中,然后在获得所有数据后尝试指定您要在单击按钮时附加到(“#YourFormID”),或者根据需要。当我使用模态时,这对我有用,希望它对你有所帮助。祝你好运

于 2014-10-28T16:17:43.183 回答
0

通常,模态弹出窗口在body. 我很确定引导程序会做同样的事情。反过来,这意味着模式的内容被移动到一个新位置并从你的form元素中取出。我建议重新排序:移动form模态窗口内部:

<div class="modal-body">
    @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.AntiForgeryToken()
        ...
    }
</div>

当模态建立时,这将移动整个表单(而不仅仅是表单元素)。

于 2014-10-28T07:36:14.960 回答
0

如果我理解您在部分视图中制作表单,并且此部分用于模式弹出窗口,那就对了。

1) 使用表单的所有元素制作一个用于表单的模型,2) 在局部视图的第一行中声明模型 3) 将模型作为参数传递给 post 函数。4)你使用了一个Partial视图,也可以在不同的页面中使用这个视图,你需要指定控件来处理表单。在代码中:

模型

public partial class SliderModel
{
    [Required]
    [StringLength(200)]
    public string FileName { get; set; }

    [StringLength(200)]
    public string Title { get; set; }

    [StringLength(1000)]
    public string Description { get; set; }

    public int? Order { get; set; }

    [NotMapped]
    public HttpPostedFileBase ImageFile { get; set; }
}

看法

@model YOURNAMESPACE.Models.SliderModel
<form method="post" class="form-horizontal" role="form" id="sendMail" 
    enctype="multipart/form-data"  action="/CONTROLLERNAME/EditSlider">

@Html.AntiForgeryToken()
<div class="modal-body">
    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.FileName, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.FileName, new { @class = "form-control", @readonly = "readonly" })
                @Html.ValidationMessageFor(model => model.FileName, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.ImageFile, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.ImageFile, new { @class = "form-control", type = "file" })
               //This is Same as below
               //<input class="form-control" id="ImageFile" name="ImageFile" type="file" value="">
            </div>
        </div>
<div class="form-group">
        <div class="col-md-offset-1">
            <button type="submit" class="btn btn-success"><b><i class="fa fa-envelope"></i> Envoyer</b> </button>
        </div>
    </div>
</form>

控制器

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditSlider(SliderModel obj)
{
    if (ModelState.IsValid)
    {
        your options
    }
    return PartialView("_EditSlider");
}
于 2014-11-01T06:52:30.320 回答
-1

尝试以下对我有用的方法:

看法 :

@using (Html.BeginForm("ComplaintAndSuggestion", "RegisterComplaints", FormMethod.Post, new { enctype = "multipart/form-data", id = "ajaxUploadForm" }))
{
:
:
:

                    <div class="row mb10">
                        <div class="col-sm-3 col-md-3">
                            <label for="file1">Upload Image 1</label>
                            <input type="file" name="images" id="file1" accept="image/*" />
                        </div>
                        <div class="col-sm-3 col-md-3">
                            <label for="file2">Upload Image 2</label>
                            <input type="file" name="images" id="file2" accept="image/*" />
                        </div>
                        <div class="col-sm-3 col-md-3">
                            <label for="file3">Upload Image 3</label>
                            <input type="file" name="images" id="file3" accept="image/*" />
                        </div>
                        <div class="col-sm-3 col-md-3">
                            <label for="file4">Upload Image 4</label>
                            <input type="file" name="images" id="file4" accept="image/*" />
                        </div>
                    </div>

   <input type="submit" value="Create" />

}

控制器 :

     [HttpPost]
        public ActionResult ComplaintAndSuggestion(Register register, IEnumerable<HttpPostedFileBase> images, IEnumerable<HttpPostedFileBase> videos)
        {


 foreach (var file in images)
                {

                    if (file != null)
                    {
                        string filenameWithDateTime = AppendTimeStamp(file.FileName);
                        file.SaveAs(Server.MapPath(Path.Combine("~/Images/", filenameWithDateTime)));
                        fileUploadModel.FilePath = (Server.MapPath(Path.Combine("~/Images/", filenameWithDateTime)));
                        fileUploadModel.FileName = filenameWithDateTime;
                        fileUploadModel.FileType = "Image";
                        fileUploadModel.RegisterId = register.RegisterId;
                        mediaRepository.Add(fileUploadModel);
                        mediaRepository.Save();
                    }

                }

}

让我知道。

于 2014-10-25T15:55:11.400 回答