MVC - не сохранять нулевые данные изображения, если изображение не было повторно загружено в HTTP-сообщении (из примера SportsStore) - PullRequest
2 голосов
/ 28 декабря 2011

Я следил за примером проекта SportsStore в книге Apress Pro ASP.NET MVC 3 Framework и пытался применить концепции к моему приложению. Меня беспокоит одна область: в образце я могу добавить изображение в продукт, и оно будет сохранено в базе данных, но если я отредактирую какой-либо продукт, не загружая для него новое изображение, данные изображения будут удалены. , Я хочу иметь возможность редактировать продукт, но если данные изображения, возвращаемые из сообщения HTTP, являются нулевыми, я хочу, чтобы Entity Framework сохранил существующие данные изображения (и тип содержимого). Как я могу дать команду EF не обновлять это поле изображения с нулем, если новое изображение не загружено?

Вот код редактирования из образца 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 ]

2 голосов
/ 30 мая 2013

Я знаю, что уже немного поздно отвечать, но сейчас я просто прорабатываю эту главу и у меня возникла та же проблема.

Я исправил это, добавив скрытое поле в окно редактирования для хранения данных 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")
}
2 голосов
/ 28 декабря 2011

Основная проблема заключается в том, что при сохранении Product обратно в базу данных вы перезаписываете поля ImageMimeType и ImageData любыми значениями, которые MVC3 заполняет в Product из 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);
}

Очевидно, что эти два метода на самом деле не существуют, но идея одна и та же.Вы хотите получить существующие значения из БД для этого Продукта и убедиться, что они отражены в локальной версии Product, прежде чем сохранить и перезаписать значения.

...