我正在研究MVC / EF Web应用程序。在其中一种形式中,我编辑了一个模型。该模型具有图像字段(public byte[] BioPhoto)
当我将图片上传到该字段并保存数据时,ModelState.IsValid
为false
,因为ModelState中的BioPhoto
属性为null
。请注意,模型中的BioPhoto加载了图像数据。
我尝试使用下面的代码将图片注入ModelState,但ModelState.IsValid
仍为false
public ActionResult Edit([Bind(Include = "BusinessId,Name,About,Phone,TollFree,FAX,Email,Bio,BioPhoto")] Business business)
{
if (System.IO.File.Exists("image.jpg"))
{
business.BioPhoto = System.IO.File.ReadAllBytes("image.jpg");
ModelState.SetModelValue("BioPhoto",
new ValueProviderResult(business.BioPhoto, "", System.Globalization.CultureInfo.InvariantCulture));
}
if (ModelState.IsValid)
{
db.Entry(business).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(business);
}
我做错了什么。对于这个问题有没有更好的解决方案?
我在SO中读了几个答案,但无法弄清楚如何解决我的问题。
这是我的模特
public class Business
{
public int BusinessId { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[Required]
public Address address { get; set; }
[Required]
[StringLength(20)]
public string Phone { get; set; }
[StringLength(20)]
public string TollFree { get; set; }
[StringLength(20)]
public string FAX { get; set; }
[Required]
[StringLength(50)]
public string Email { get; set; }
[Required]
[StringLength(100)]
public string WebSite { get; set; }
[Required]
public string About { get; set; }
[Required]
public string Bio { get; set; }
[Required]
public byte[] BioPhoto { get; set; }
}
我的观点
<div class="form-group">
@Html.LabelFor(model => model.BioPhoto, "BIO Photo (Best Size: 350 x 450)", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<form enctype="multipart/form-data">
<div class="form-group" style="width:400px">
<input id="BioPhoto" type="file" multiple class="file" data-overwrite-initial="false" />
</div>
</form>
@Html.ValidationMessageFor(model => model.BioPhoto, "", new { @class = "text-danger" })
</div>
</div>
答案 0 :(得分:2)
就像我说的那样,问题是表单没有将BioPhoto
发布到控制器 - 最有可能。您可以使用Chrome查看http请求正文中的内容。
如果您想要添加图像,即使控制器没有接收到它,请尝试此操作。
尝试仅删除与图像属性相关的错误:
ModelState["BioPhoto"].Errors.Clear();
然后添加图片:
business.BioPhoto = System.IO.File.ReadAllBytes("image.jpg");
然后更新模型:
UpdateModel(business);
现在,如果您致电ModelState.IsValid
,则需要考虑BioPhoto
的设置并重新评估IsValid
。
编辑:
我建议打电话
ModelState.SetModelValue("BioPhoto", new ValueProviderResult(business.BioPhoto, "", System.Globalization.CultureInfo.InvariantCulture));
实际将值推送到ModelState.Values。但这不是必要的。
答案 1 :(得分:0)
由于您未使用视图模型,因此应为图像使用类型为HttpPostedFileBase
的参数。然后在您的操作方法中,您可以convert it's InputStream property value to byte array并保存它。
public ActionResult Edit([Bind(Include = "BusinessId,Name,About,Phone,TollFree,
FAX,Email,Bio")] Business business,HttpPostedFileBase BioPhoto)
{
// to do read BioPhoto.InputStream and convert to your byteArray
// to do :Return something
}
您必须从模型类的字节数组属性中删除[Required]
属性。
最佳解决方案是使用视图模型,该视图模型仅包含您所需的属性。您不需要每次都从编辑屏幕重新发布图像。仅当用户在编辑表单中选择新图像时才更新该属性。如果不是,请在保存时不更新该列的现有值。
public class EditBusinessVm
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[Required]
public Address address { get; set; }
[Required]
[StringLength(20)]
public string Phone { get; set; }
public HttpPostedFileBase BioPhoto { set;get;}
// Add other properties as needed.
}
现在您的观点必须强烈输入此类
@model EditBusinessVm
@using(Html.BeginForm())
{
@Html.TextBoxFor(s=>s.Name)
<input type="file" name="BioPhoto" />
@Html.HiddenFor(f=>f.Id)
<!-- add other fields needed -->
<input type="submit" />
}
并且您的httppost操作方法将使用此类型作为参数
public ACtionResult Edit(EditBusinessVm model)
{
// purposefully omitting null checks/model validations code here
//get existing entity
var b=db.Businesses.FirstOrDefault(f=>f.BusinessId==model.Id);
//update the properties from the posted view model
b.Name = model.Name;
if(model.BioPhoto!=null) // user selected a new photo.
b.BioPhoto = GetByteArray(model.BioPhoto);
// to do : Set other properties as well.
db.Entry(business).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
private byte[] GetByteArray(HttpPostedFileBase file)
{
MemoryStream target = new MemoryStream();
file.InputStream.CopyTo(target);
return target.ToArray();
}