MVC - 如果未在HTTP帖子中重新上传图像,则不保存空图像数据(来自SportsStore示例)

时间:2011-12-27 21:05:54

标签: asp.net-mvc entity-framework http-post httppostedfilebase

我一直关注Apress Pro ASP.NET MVC 3框架书中的SportsStore示例项目,并尝试将这些概念应用到我的应用程序中。困扰我的一个方面是,在示例中,我可以将图像添加到产品中并将其保存到数据库中,但如果我编辑任何给定的产品,而不上传新的图像,则图像数据将被清除。我希望能够编辑产品,但如果从HTTP帖子返回的图像数据为空,我希望实体框架保留现有的图像数据(和内容类型)。如果没有上传新图像,如何命令EF不使用null更新此图像字段?

以下是来自SportsStore示例的编辑代码:

[HttpPost]
public ActionResult Edit(Product product, HttpPostedFileBase image)
{
  if (ModelState.IsValid)
  {
    if(image != null)
    {
      product.ImageMimeType = image.ContentType;
      product.ImageData = new byte[image.ContentLength];
      image.InputStream.Read(product.ImageData, 0, image.ContentLength);
    }
    _repository.SaveProduct(product);
    TempData["message"] = string.Format("{0} has been saved", product.Name);
    return RedirectToAction("Index");
  }
  else
  {
    return View(product);
  }
}

编辑:对于Rondel - 以下是产品类的定义

namespace SportsStore.Domain.Entities
{
  public class Product
  {
    [HiddenInput(DisplayValue=false)]
    public int ProductId { get; set; }

    [Required(ErrorMessage = "Please enter a product name")]
    public string Name { get; set; }

    [Required(ErrorMessage = "Please enter a description")]
    [DataType(DataType.MultilineText)]
    public string Description { get; set; }

    [Required]
    [Range(0.01, double.MaxValue, ErrorMessage = "Please enter a positive price")]
    public decimal Price { get; set; }

    [Required(ErrorMessage = "Please specify a category")]
    public string Category { get; set; }

    public byte[] ImageData { get; set; }

    [HiddenInput(DisplayValue = false)]
    public string ImageMimeType { get; set; }
  }
}

编辑如何让EF只保存某些字段并让其他字段保持不变?

2 个答案:

答案 0 :(得分:2)

这里的基本问题是,当您将Product保存回数据库时,您将使用MVC3填充ImageMimeType的任何值覆盖ImageDataProduct字段来自FormCollection。现在,您要检查是否image==null但是您没有实现逻辑以重用旧的Product图像信息。这是你想要做的:

if (ModelState.IsValid)
{
  if(image != null)
  {
     product.ImageMimeType = image.ContentType;
     product.ImageData = new byte[image.ContentLength];
     image.InputStream.Read(product.ImageData, 0, image.ContentLength);
  }
 else
 {
    //set this Product image details from the existing product in the db
    product.ImageMimeType= getImageMimeTypeForProduct(product.ProductId );
    product.ImageData = getImageDataForProduct(product.ProductId );
 }
  _repository.SaveProduct(product);
  TempData["message"] = string.Format("{0} has been saved", product.Name);
  return RedirectToAction("Index");
}
else
{
  return View(product);
}

显然,这两种方法并不存在,但这个想法是一样的。您希望从该产品的db获取现有值,并确保在保存它并覆盖值之前将这些值反映在Product的本地版本中。

答案 1 :(得分:2)

我知道回复有点迟,但我现在正在完成这一章并遇到同样的问题。

我通过在编辑视图中添加隐藏字段来修复它,以保存ImageData数据。由于视图使用@ Html.EditorForModel,因此不会为字节数据类型呈现任何编辑器,因此视图无法看到此数据。

@model SportsStore.Domain.Entities.Product

@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

<h1>Edit @Model.Name</h1>

@using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype = "multipart/form-data"}))
{
    @Html.EditorForModel()

    // New hidden field here
    @Html.Hidden("ImageData", Model.ImageData)

    <div class="editor-label">Image</div>
    <div class="editor-field">
        @if (Model.ImageData == null)
        {
            @:None
        }
        else
        {
            <img width="150" height="150" src="@Url.Action("GetImage", "Product", new { Model.ProductID})" />
        }
        <div>Upload new image: <input type="file" name="Image" /></div>
    </div>

    <input type="submit" value="Save" />
    @Html.ActionLink("Cancel and return to List", "Index")
}