【问题标题】:Using ajax to post a view model which includes an IFormFile property in MVC Core使用 ajax 在 MVC Core 中发布包含 IFormFile 属性的视图模型
【发布时间】:2018-03-14 22:55:12
【问题描述】:

我正在尝试使用 jquery AJAX 帖子在 MVC 核心中发布一个简单的视图模型,但是模型上的 IFormFile 属性似乎为空。

我有以下视图模型:

    [Required]
    public IFormFile File { get; set; }

    [Required]
    [Display(Name = "Owner")]
    public int DocumentOwner { get; set; }

    [Required]
    [Display(Name = "Document Type")]
    public int DocumentTypeId { get; set; }

然后我在视图底部的脚本中使用 jQuery ajax 帖子:

$("form").submit(function (e) {
    e.preventDefault();

    var model = $('form').serialize();

    $.ajax({
        type: "POST",
        url: "/Client/AddDocument",
        contentType: false,
        processData: false,
        data: model,
        success: function (message) {
            alert(message);
        },
        error: function () {
            alert("There was error uploading files!");
        }
    });
});

viewmodel 已成功将其他值传递给控制器​​,但是文件以 null 的形式通过。

有人可以帮忙吗?

【问题讨论】:

  • var model = $('form').serialize(); 更改为 var model = new FormData($('form').get(0)); - 请参阅 this answer
  • 感谢斯蒂芬,这非常有效。

标签: jquery ajax asp.net-mvc asp.net-core


【解决方案1】:

不幸的是,jQuery serialize() 方法不会包含输入文件元素。所以选择的文件用户不会包含在序列化值中。

您可以做的是,创建一个FormData 对象,将文件附加到该对象。您还需要将表单字段值附加到同一 FormData 对象。您可以简单地遍历所有输入字段并添加它。另外,在ajax调用中,需要将processDatacontentType属性值指定为false

这应该可以工作

$(function () {

    $("form").submit(function (e) {
        e.preventDefault();

        var formAction = $(this).attr("action");
        var fdata = new FormData();

        var fileInput = $('#File')[0];
        var file = fileInput.files[0];
        fdata.append("File", file);

        // You can update the jquery selector to use a css class if you want
        $("input[type='text'").each(function (x, y) {
            fdata.append($(y).attr("name"), $(y).val());
        });

        $.ajax({
            type: 'post',
            url: formAction ,
            data: fdata,
            processData: false,
            contentType: false
        }).done(function(result) {
            // do something with the result now
            console.log(result);
        });

    });

 });

上面的代码是从表单(已经提交)中读取 action 属性,并将其用作 ajax 表单提交的 url。

@model YourViewModel
<form asp-action="Index" asp-controller="Home" method="post" >

    <label asp-for="DocumentOwner"></label>
    <input type="text" asp-for="DocumentOwner" />

    <label asp-for="DocumentTypeId"></label>
    <input type="text" asp-for="DocumentTypeId" />

    <label asp-for="File"></label>
    <input asp-for="File" />

    <input type="submit"  />
</form>

在您的 HttpPost 操作方法中,您可以使用与参数相同的视图模型。下面的示例代码读取File属性并将其保存到wwwroot目录内的uploads目录中。

public class HomeController : Controller
{
    private readonly IHostingEnvironment hostingEnvironment;
    public HomeController(IHostingEnvironment environment)
    {
        hostingEnvironment = environment;
    }
    [HttpPost]
    public IActionResult Index(YourViewModel vm)
    {
        if (ModelState.IsValid)
        {
            if (vm.File != null)
            {
                var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
                var filePath = Path.Combine(uploads, GetUniqueFileName(vm.File.FileName));
                vm.File.CopyTo(new FileStream(filePath, FileMode.Create));
                return Json(new {status = "success", message = "Successfully saved"});
            }
        }
        else
        {
            // handle what to do when model validation fails
        }
        return Json(new {status = "error", message = "something wrong!"});
    }
    private string GetUniqueFileName(string fileName)
    {
        fileName = Path.GetFileName(fileName);
        return  Path.GetFileNameWithoutExtension(fileName)
                  + "_" + Guid.NewGuid().ToString().Substring(0, 4) 
                  + Path.GetExtension(fileName);
    }
}

【讨论】:

  • 这个答案非常有用。
猜你喜欢
  • 2019-09-27
  • 1970-01-01
  • 2016-10-04
  • 1970-01-01
  • 1970-01-01
  • 2017-09-06
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多