Having successfully loaded the image in mvc 3, but when editing the image it goes away

I am reading Pro ASP.NET MVC 3 Framework from Apress. I follow the example of loading and displaying images. The problem is that it works great when uploading images to products, but if I later want to edit the description, for example, and then save the product, the image will disappear. I understand that the problem is that when I save the product, I do not transfer image data, because the image loading is empty, and context.SaveChanges () saves every data field, including data fields with empty images.

I am stuck and I would really appreciate it if anyone could help me!

This is part of the edit page:

<label>Image</label> if (Model.ImageData == null) { @:Null } else { <img id="imageFile" runat="server" src="@Url.Action("GetImage", "Product", new { Model.Name })" /> } <label>Upload image:</label> <input type="file" name="Image" runat="server" /> 

When updating:

 public ActionResult Edit(Product product, HttpPostedFileBase image) { if (ModelState.IsValid) { if (image != null && image.ContentLength > 0) { 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} har sparats", product.Name); return RedirectToAction("Index"); } else { return View(product); } } 

Product Saving:

 public void SaveProduct(Product product) { if (product.ProductID == 0) { context.Products.Add(product); } else { context.Entry(product).State = EntityState.Modified; } int result = context.SaveChanges(); } 
+4
source share
3 answers

Your understanding of the problem is correct: when you mark your Product as EntityState.Modified , EF notes that all its properties are changed. Therefore, when your current Product arrives from the controller and has no image, EF removes it from the database when calling SaveChanges() .
I see two options:

  • Download the original Product and simply update the required properties with EntityState.Modified :

     var productInDb = context.Products.Find(product.Id); productInDb.Name = product.Name; productInDb.Description = product.Description; if (product.ImageData !=null ) { productInDb.ImageData = product.ImageData; productInDb.ImageMimeType = product.ImageMimeType; } 

    In this case, you need to manually set each property to Product .

  • After you have marked your Product as modified, you will reset the image values ​​from db:

     context.Entry(product).State = EntityState.Modified; if (product.ImageData == null) { var databaseValues = context.Entry(product).GetDatabaseValues(); product.ImageData = (byte[])databaseValues["ImageData"]; product.ImageMimeType = (string)databaseValues["ImageMimeType"]; } 

    In this case, you only need to re-set the properties associated with the image.

In both implementations, there is no way to remove ImageData during the upgrade.

+4
source

If you try the second option provided by @nemesv, and your entity classes are in a different namespace relative to your DbContext, then you will get an exception thrown by the entity framework, as described here:

entry.GetDatabaseValues ​​() throw EntitySqlException

Type 'XXX' may not be found. Ensure that the necessary schemas are loaded and that the namespaces are imported correctly.

http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/fa67aa0e-3bca-44a5-9e00-af6362a539a7

It seems that there is work, but it is not like it. However, this allows you to display the image associated with the product.

Here is how I did it:

 if (product.ImageData == null) { // Get Product Context reference var productContext = context.Entry(product); productContext.State = EntityState.Modified; // Copy client values and reload orignal product values from DB. var clientValues = productContext.CurrentValues.Clone().ToObject(); productContext.Reload(); productContext.CurrentValues.SetValues(clientValues); // Get database values (Original) var currentValues = productContext.Entity; var databaseValues = (Product)productContext.OriginalValues.ToObject(); // Change image properties to match original values productContext.Entity.ImageData = databaseValues.ImageData; productContext.Entity.ImageMimeType = databaseValues.ImageMimeType; } 
0
source

I had a similar problem. When I added @Html.HiddenFor(model => model.Image) to my editable view, it passed imageURL perfectly.

0
source

Source: https://habr.com/ru/post/1385624/


All Articles