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

发布于 2024-12-23 00:12:21 字数 1735 浏览 2 评论 0原文

我一直在关注 Apress Pro ASP.NET MVC 3 Framework 书中的 SportsStore 示例项目,并尝试将这些概念应用到我的应用程序中。困扰我的一个地方是,在示例中,我可以将图像添加到产品中并将其保存到数据库中,但是如果我编辑任何给定产品,而不为其上传新图像,则图像数据将被清除。我希望能够编辑产品,但如果从 HTTP post 返回的图像数据为空,我希望实体框架保留现有的图像数据(和内容类型)。如果未上传新图像,如何命令 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 仅保存某些字段并保留其他字段数据库中未受影响?

I have been following the SportsStore example project in Apress Pro ASP.NET MVC 3 Framework book and trying to apply the concepts to my application. One area that is bugging me is that in the sample, I can add an image to a product and it gets saved to the database, but if I edit any given product, without uploading a new image for it, the image data is cleared out. I want to be able to edit a product, but if the image data returned from the HTTP post is null, that I want Entity Framework to keep the exisiting image data (and content type). How can I command EF to not update this image field with null if a new image isn't uploaded?

Here is the Edit code from the SportsStore sample:

[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);
  }
}

EDIT: For Rondel - Here is the definition of the Product class

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; }
  }
}

EDIT How can I make EF save only certain fields and leave others untouched in the database?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半岛未凉 2024-12-30 00:12:21

这里的基本问题是,当您将 Product 保存回数据库时,您将使用 MVC3 填充的任何值覆盖 ImageMimeTypeImageData 字段来自 FormCollectionProduct。现在,您需要检查 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 的本地版本中,然后再保存并覆盖这些值。

The basic problem here is that when you save the Product back to the database, you are overwriting the ImageMimeType and ImageData fields with whatever values MVC3 populates that Product with from the FormCollection. Right now you have a check to see if the image==null but you did not implement the logic to reuse the old Product image information. Here is what you want to do:

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);
}

Obviously those two methods don't really exist but the idea is the same. You want to get the existing values from the db for that Product and ensure that those are reflected in the local version of the Product before you save it and overwrite the values.

猫七 2024-12-30 00:12:21

我知道回复有点晚了,但我现在刚刚读完这一章,遇到了同样的问题。

我通过在编辑视图中添加一个隐藏字段来保存 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")
}

I know its a bit late in replying but I'm just working through this chapter now and had the same issue.

I fixed it by adding a hidden field to the edit view to hold the ImageData data. As the view uses @Html.EditorForModel this does not render any editor for a byte data type, therefore the view has no visibility of this data.

@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")
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文