我有以下型号:
public class Photo
{
public int PhotoId { get; set; }
public byte[] ImageData { get; set; }
public DateTime DateUploaded { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
}
我希望用户能够输入照片的详细信息,然后将模型发布到控制器。我的控制器操作如下:
[HttpPost]
public ActionResult Create(WilhanWebsite.DomainClasses.Photo photo)
{
if (ModelState.IsValid)
{
photo.DateUploaded = DateTime.Now;
_context.Photos.Add(photo);
_context.SaveChanges();
return RedirectToAction("Index");
}
//we only get here if there was a problem
return View(photo);
}
我的观点如下:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Photo</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.ImageData, new { @class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="uploadImages" class="input-files" />
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.DateUploaded, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.DateUploaded)
@Html.ValidationMessageFor(model => model.DateUploaded)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.IsActive, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.IsActive)
@Html.ValidationMessageFor(model => model.IsActive)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
视图显示正常,允许用户从本地磁盘中选择文件并输入其他模型详细信息。 我的问题是虽然模型被发布到控制器ok,但是描述,日期和IsActive标志填充正确 - 图像数据为空。
有谁能告诉我需要更改的内容,以便将照片的字节数组包含在发布到控制器的模型中?
答案 0 :(得分:25)
视图中的文件输入名称为uploadImages
。我在视图模型中看不到具有此名称的属性。您似乎有一些ImageData
属性是一个字节数组,但在您的视图中似乎没有相应的输入字段。
这解释了为什么你得到null。您可以通过尊重惯例来完成这项工作。例如,如果您打算在视图中包含这样的输入字段:
<input type="file" name="uploadImages" class="input-files" />
然后确保您的视图模型上的属性具有相同的名称。当然还有类型HttpPostedFileBase
。
public HttpPostedFileBase UploadImages { get; set; }
同样在您的视图中,请确保您设置了multipart/form-data
的正确内容类型:
@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
}
您可能希望通过following blog post
来更好地熟悉如何在ASP.NET MVC中上传文件的基础知识。我还写了一篇你可以咨询的similar answer here
。
因此,一旦在视图模型中添加HttpPostedFileBase
名称为UploadImages
的属性,就可以调整控制器操作以读取字节数组并将其存储为ImageData
属性:
[HttpPost]
public ActionResult Create(WilhanWebsite.DomainClasses.Photo photo)
{
if (ModelState.IsValid)
{
photo.DateUploaded = DateTime.Now;
photo.ImageData = new byte[photo.UploadImages.ContentLength];
photo.UploadImages.Read(photo.ImageData, 0, photo.ImageData.Length);
_context.Photos.Add(photo);
_context.SaveChanges();
return RedirectToAction("Index");
}
//we only get here if there was a problem
return View(photo);
}
现在请记住,这是一个非常糟糕的解决方案。永远不要在现实世界的应用程序中这样做在正确设计的应用程序中,您将拥有一个视图模型,您的控制器操作将将其作为参数。您永远不会直接使用自动生成的EF模型作为控制器操作的参数。您将拥有一个具有HttpPostedFileBase
属性的视图模型,该属性将映射到您的域模型。
因此,在设计合理的应用程序中,您将拥有一个PhotoViewModel
视图模型类,您的控制器操作将采用该类。
答案 1 :(得分:3)
更改此行:
@using (Html.BeginForm())
对此:
@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
然后改变:
<input type="file" name="uploadImages" class="input-files" />
要:
<input type="file" name="ImageData" class="input-files" />
然后改变这一行:
public byte[] ImageData { get; set; }
对此:
public HttpPostedFileBase ImageData { get; set; }
最后,使用这样的代码将图像读入字节数组:
var bs = new byte[ImageData.ContentLength];
using (var fs = ImageData.InputStream)
{
var offset = 0;
do
{
offset += fs.Read(bs, offset, bs.Length - offset);
} while (offset < bs.Length);
}
答案 2 :(得分:1)
查看:
@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
...
<input type="file" id="ImageFile" name="ImageFile" .../>
...
}
控制器:
[HttpPost]
public ActionResult Create(Photo photo, HttpPostedFileBase ImageFile)
{
byte[] buf = new byte[ImageFile.ContentLength];
ImageFile.InputStream.Read(buf, 0, buf.Length);
photo.ImageData = buf;
...
}