使用ajax发布视图模型,其中包含MVC Core中的IFormFile属性

时间:2017-10-03 16:58:28

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

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

我有以下视图模型:

    [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形式传递。

任何人都可以提供帮助吗?

1 个答案:

答案 0 :(得分: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属性并将其保存到uploads目录中的wwwroot目录。

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