我试图使用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形式传递。
任何人都可以提供帮助吗?
答案 0 :(得分:1)
不幸的是,jQuery serialize()
方法不包含输入文件元素。因此,所选的文件用户不会包含在序列化值中。
您可能要做的是,创建一个FormData
对象,将文件附加到该对象。您还需要将表单字段值附加到同一个FormData
对象。您可以简单地遍历所有输入字段并添加它。此外,在ajax调用中,您需要将processData
和contentType
属性值指定为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);
}
}