我在视图上有一组带有一组输入的常规表单。我使用jQuery来序列化并发布它。
$("#formId").submit(function (e) {
e.preventDefault();
var fields = {};
var formSerialized = $("#formId").serializeArray();
$.each(formSerialized, function (i, field) {
fields[field.name] = field.value; });
e.data = fields;
$.post("myUrl", {
FirstName: e.data.FirstName,
LastName: e.data.LastName
}, function (success) {
if (success) {
alert('Ok')
} else {
alert('fail');
}
});
}
});
在后端,我有ASP.NET WebAPI2服务器,其中包含获取此请求的操作,并自动将所有属性绑定到模型。
现在我需要将多个文件输入添加到同一表单中。
有没有办法: - 在同一个请求中同时发送我在代码示例中发送的文件和常规属性? - 是否可以使用HttpPostedFileBase属性在WebAPI端扩展模型并保持数据的自动绑定?
在同一个请求中发送常规文本属性(表单中的值)+多个文件以在WebAPI2端的单个方法中处理它们的最佳方法是什么?
谢谢!
答案 0 :(得分:1)
此答案讨论了一些选项,但您可能会遇到一些浏览器兼容性问题:
如果是一个选项,您可以考虑定期进行非异步表单提交,并确保您的表单具有enctype =“multipart / form-data”,但如果没有,您可以尝试该链接中讨论的一些内容。希望这有帮助
编辑 - 另一种方法是使用这个jQuery表单插件:http://malsup.com/jquery/form/
在这种情况下,我没有使用viewmodel,而是将输入直接绑定到参数,但我想不出任何理由为什么它与典型的vm完全不同。
使用示例:
前端
@using (Html.BeginForm("SaveComment", "Comments", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
[text and file inputs, submit button]
}
<script>
$('#addNote form').ajaxForm({
success: function (response) {
$.notify(response.result, {
className: "success",
position: "top center"
});
//reload comments section
$.ajax({
url: './Comments/Index',
data: {
labelId: '@Model.LabelId',
orderNumber: '@Model.OrderNumber'
},
success: function (response) {
$('#commentsSection').html(response);
}
});
},
error: function () {
$.notify("Failed to save note");
},
beforeSubmit: function () {
$('#addNote').modal('toggle');
}
});
后端
public JsonResult SaveComment(string saveNote, string labelId, string orderNumber, string comment, string criteria, HttpPostedFileBase file)
{
[text input named saveNote went into saveNote param]
[file input named file went into HttpPostedFileBase file param]
[...process other params...]
var ms = new MemoryStream();
file.InputStream.CopyTo(ms);
deliveryItemComment.Attachment = ms.ToArray();
db.SaveChanges();
var result = "Note Succesfully Added";
return Json(new { result = result }, JsonRequestBehavior.AllowGet);
}
答案 1 :(得分:0)
我想是非常丑陋的解决方案,但我以这种方式结束了。
JS使用表单数据:
var formSerialized = $("formId").serializeArray();
var data = new FormData();
var files = $("#fileInputId").get(0).files;
data.append("File", files[0]);
$.each(formSerialized, function (i, field) {
data.append(field.name, field.value);
});
$.ajax({
type: "POST",
contentType: false,
processData: false,
url: "some URL",
data: data
}
});
在WebAPI方面,我必须分别从表单数据中读取表单字段和文件:
var myModel = new MyModel();
var root = HttpContext.Current.Server.MapPath("~/App_Data/");
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
//Maps fields from form data into my custom model
foreach (var key in provider.FormData.AllKeys)
{
var value = provider.FormData.GetValues(key).FirstOrDefault();
if (value != null && value != "undefined")
{
var prop = myModel.GetType().GetProperty(key);
if (prop != null)
{
prop.SetValue(myModel, value, null);
}
}
}
//Resaves all files in my custom location under App_Data and puts their paths into list
var fileNames = new Collection<string>();
foreach (var file in provider.FileData)
{
var fileExt = file.Headers.ContentDisposition.FileName.Split('.').Last().Replace("\"", string.Empty);
var combinedFileName = string.Format("{0}.{2}", file.Headers.ContentDisposition.Name.Replace("\"", string.Empty), fileExt);
var combinedPath = Path.Combine(root + "CustomDirectory/", combinedFileName);
File.Move(file.LocalFileName, combinedPath);
fileNames.Add(combinedPath);
}