Reputation: 13
hi every one first time to ask here. So here is my Create post method on multiple images plus other data entries and it works with out any problem and it uploads all images and the content. My question is how to handle edit Post controller on multiple images.
here is the Create controller
public ActionResult SaveDataAdded([Bind(Include = "SId,Category,SName,LocalName,CommonName,Description,PicTakenBy,ContentBy,EditedBy")]SpeciesDataTable ARow, HttpPostedFileBase file,HttpPostedFileBase file2, HttpPostedFileBase file3, HttpPostedFileBase file4)
{if (ModelState.IsValid)
{
if (file != null && file.ContentLength > 0)
{
using (var Bnryreader = new System.IO.BinaryReader(file.InputStream))
{
ARow.MainPic = Bnryreader.ReadBytes(file.ContentLength);
}
}
if (file2 != null && file2.ContentLength > 0)
{
using (var reader = new System.IO.BinaryReader(file2.InputStream))
{
ARow.SecPic = reader.ReadBytes(file2.ContentLength);
}
}
if (file3 != null && file3.ContentLength > 0)
{
using (var reader = new System.IO.BinaryReader(file3.InputStream))
{
ARow.ThirdPic = reader.ReadBytes(file3.ContentLength);
}
}
if (file4 != null && file4.ContentLength > 0)
{
using (var reader = new System.IO.BinaryReader(file4.InputStream))
{
ARow.FourthPic = reader.ReadBytes(file4.ContentLength);
}
}
db.SpeciesDataTables.Add(ARow);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(ARow);
}
and here is the code block for edit. Probably my approach was not correct. But i need help on this.
public ActionResult EditSpeciesPost([Bind(Include = "SId,Category,SName,LocalName,CommonName,Description,PicTakenBy,ContentBy,EditedBy")]SpeciesDataTable Editor, HttpPostedFileBase file, HttpPostedFileBase file2, HttpPostedFileBase file3, HttpPostedFileBase file4)
{
if (file != null && file.ContentLength > 0)
{
using (var reader = new System.IO.BinaryReader(file.InputStream))
{
Editor.MainPic = reader.ReadBytes(file.ContentLength);
}
}
if (file2 != null && file2.ContentLength > 0)
{
using (var reader = new System.IO.BinaryReader(file2.InputStream))
{
Editor.SecPic = reader.ReadBytes(file2.ContentLength);
}
}
if (file3 != null && file3.ContentLength > 0)
{
using (var reader = new System.IO.BinaryReader(file3.InputStream))
{
Editor.ThirdPic = reader.ReadBytes(file3.ContentLength);
}
}
if (file4 != null && file4.ContentLength > 0)
{
using (var reader = new System.IO.BinaryReader(file4.InputStream))
{
Editor.FourthPic = reader.ReadBytes(file4.ContentLength);
}
}
db.Entry(Editor).State = EntityState.Modified;
db.SaveChanges();
//return RedirectToAction("Index");
return View(Editor);
}
here is the view for edit
@using(Html.BeginForm("EditSpecies", "Species", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<div class="col-md-10">
@if (Model.MainPic != null) // to view first image
{
var base64 = Convert.ToBase64String(Model.MainPic);
var imgsrc = string.Format("data:image/jpg;base64,{0}", base64);
<img src='@imgsrc' style="max-width:100px;max-height:100px" />
}
</div>
<div class="col-md-10">
<input type="file" name="file" /> // input for first image
</div>
<div class="col-md-10">
@if (Model.SecPic != null)// to view second image
{
var base64 = Convert.ToBase64String(Model.SecPic);
var imgsrc = string.Format("data:image/jpg;base64,{0}", base64);
<img src='@imgsrc' style="max-width:50px;max-height:50px" />
}
</div>
<div class="col-md-10">
<input type="file" name="file2" /> input for third image
</div>
// and it continues to third and fourth picture
}
Upvotes: 1
Views: 1015
Reputation: 218762
What you should be doing is, sending only null for the images user has not updated in the UI and post the data to the httppost action method where you read the existing entity and update only those properties needed to update.
I would create a view model for my view with properties needed for the view.
public class SpeciesVm
{
public int Id { set; get; }
public string Name { set; get; }
public string LocalName { set; get; }
public HttpPostedFileBase MainImg { set; get; }
public HttpPostedFileBase SecondImg { set; get; }
public string MainPicImgSrc { set; get; }
public string SecondPicImgSrc { set; get; }
}
Now in your GET action, you create an object of this, load the property values.
public ActionResult Edit(int id)
{
var e=db.SpeciesDataTables.Find(id);
var vm = new SpeciesVm() { Id=id , Name =e.SName };
vm.LocalName= e.LocalName;
if(e.MainPic!=null)
{
vm.MainPicImgSrc = $"data:image/jpg;base64,{Convert.ToBase64String(e.MainPic)}";
}
if(e.SecPic!=null)
{
vm.SecondPicImgSrc = $"data:image/jpg;base64,{Convert.ToBase64String(e.SecPic)}";
}
return View(vm);
}
Now in your view, you will use the properties of type HttpPostedFileBase
for the file input
@model SpeciesVm
@using (Html.BeginForm("Edit","Species", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
@Html.HiddenFor(a=>a.Id)
@Html.HiddenFor(a=>a.Name)
@Html.HiddenFor(a=>a.LocalName)
<div class="col-md-10">
@if (!string.IsNullOrEmpty(Model.MainPicImgSrc))
{
<img src='@Model.MainPicImgSrc' />
}
<input type="file" name="MainImg" />
</div>
<div class="col-md-10">
@if (!string.IsNullOrEmpty(Model.SecondPicImgSrc))
{
<img src='@Model.SecondPicImgSrc' />
}
<input type="file" name="SecondImg" />
</div>
<button type="submit">Save</button>
}
Now in your HttpPost action method, you will use the same view model as the parameter, read the Id property value, using which read existing entity and update the properties as needed.
[HttpPost]
public ActionResult Edit(SpeciesVm model)
{
var e=db.SpeciesDataTables.Find(id);
e.SName = model.Name;
//Update the image properties only if it was send from the form
if(model.MainImg!=null)
{
e.MainPic = GetByteArrayFromImage(model.MainImg);
}
if(model.MainImg!=null)
{
e.SecPic = GetByteArrayFromImage(model.SecondImg);
}
db.SaveChanges();
return RedirectToAction("Index");
}
private byte[] GetByteArrayFromImage(HttpPostedFileBase file)
{
if (file == null)
return null;
var target = new MemoryStream();
file.InputStream.CopyTo(target);
return target.ToArray();
}
Upvotes: 2