0

这是我在 StackOverflow 上的第一篇文章。我希望这很有用。

我有一个 Razor 视图,旨在允许编辑包含预定义值或空值的模型的可显示属性。视图不应更改模型属性的内容,除非用户通过在基于视图的 UI 中编辑它们来故意更改它们。视图行为正确,除了byte[]包含图像数据的类型属性:Model.ImageData

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

@Html.EditorForModel()

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

<input type="submit" value="Save" />

}

上述视图适用于模型中的所有属性,除了Model.ImageData. 在这种情况下,发布会导致任何先前设置Model.ImageData为空。Model.ImageData通过在发布之前验证是否Model.ImageData包含有效的字节数组(带有预期的图像),我已经确认在发布期间将其设置为 null。

上述视图的控制器代码为:

  public ViewResult Edit(int id)
    {
        Product product = repository.Products.FirstOrDefault(p => p.ID == id);
// breakpoint here shows that all model properties including product.ImageData are populated and valid.
        return View(product);
    }

  [HttpPost]
  public ActionResult Edit(Product product, HttpPostedFileBase Image)  
    {
        if (ModelState.IsValid)
        {
// breakpoint here shows that product.ImageData is null (but all other model properties are still populated with data).
            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);
        }
    } 

这是更新模型的存储库代码(尽管在调用此代码之前模型正在更改):

public void SaveProduct(Product product)
    {
        if (product.ID == 0)
        {
            context.Products.Add(product);  // why doesn't this try to save ID = 0 to the ID field of the product in the database??
        }
        else
        {
            Product dbEntry = context.Products.Find(product.ID);
            if (dbEntry != null)
            {
                dbEntry.Name = product.Name;
                dbEntry.Description = product.Description;
                dbEntry.Category = product.Category;
                dbEntry.Price = product.Price;
                dbEntry.ImageData = product.ImageData;
                dbEntry.ImageMimeType = product.ImageMimeType;
            }
        }
        context.SaveChanges();
    }

我究竟做错了什么?

4

1 回答 1

0

这确实是您应该考虑使用ViewModel类的地方。但是为了保持你当前的做事方式最小的变化,尝试将SaveProduct()方法修改为以下内容:

public void SaveProduct(Product product, bool updateImage = false)
{
    context.Products.Attach(product);

    // mark product as modified
    var entry = context.Entry(product);
    entry.State = EntityState.Modified;

    entry.Property(e => e.ImageData).IsModified = updateImage;
    entry.Property(e => e.ImageMimeType).IsModified = updateImage;   

    context.SaveChanges();  
}

并将控制器代码修改为:

...
var updateImage = false;
if (Image != null)
{
    updateImage = true;
    product.ImageMimeType = Image.ContentType; 
    product.ImageData = new byte[Image.ContentLength]; 
    Image.InputStream.Read(product.ImageData, 0, Image.ContentLength); 
}
repository.SaveProduct(product, updateImage);
....
于 2014-05-28T22:20:03.377 回答