This is my Album model class.
public class Album
{
[Required(ErrorMessage ="Please enter an album title.")]
public string Title { get; set; }
[Key]
public int Id { get; set; }
[Required(ErrorMessage ="Please enter an album price.")]
[Range(0.01,double.MaxValue,ErrorMessage ="Price cannot be 0 or lower.")]
public decimal Price { get; set; }
[Required]
public int ArtistId { get; set; }
[Required]
public virtual Artist Artist { get; set; }
[Required]
public int GenreId { get; set; }
[Required]
public virtual Genre Genre { get; set; }
public byte[] ImageData { get; set; }
public string ImageMimeType { get; set; }
}
The repository and the implementation of the SaveAlbum method
public interface IAlbumRepository
{
IEnumerable<Album> Albums { get; }
void SaveAlbum(Album album);
Album DeleteAlbum(int albumId);
}
public void SaveAlbum(Album album)
{
if (album.Id == 0)
{
if (context.Albums.Where(a => a.Artist.Name == album.Artist.Name).FirstOrDefault() != null)
{
album.ArtistId = context.Albums.Where(a => a.Artist.Name == album.Artist.Name).FirstOrDefault().ArtistId;
album.Artist = context.Albums.Where(a => a.Artist.Name == album.Artist.Name).FirstOrDefault().Artist;
}
if (context.Albums.Where(a => a.Genre.Name == album.Genre.Name).FirstOrDefault() != null)
{
album.GenreId = context.Albums.Where(a => a.Genre.Name == album.Genre.Name).FirstOrDefault().GenreId;
album.Genre = context.Albums.Where(a => a.Genre.Name == album.Genre.Name).FirstOrDefault().Genre;
}
context.Albums.Add(album);
}
else
{
Album dbEntry = context.Albums.Find(album.Id);
if (dbEntry!= null)
{
if (context.Albums.Where(a => a.Artist.Name == album.Artist.Name).FirstOrDefault() != null)
{
dbEntry.ArtistId = context.Albums.Where(a => a.Artist.Name == album.Artist.Name).FirstOrDefault().ArtistId;
dbEntry.Artist = context.Albums.Where(a => a.Artist.Name == album.Artist.Name).FirstOrDefault().Artist;
}
else
{
dbEntry.ArtistId = album.ArtistId;
dbEntry.Artist = album.Artist;
}
if (context.Albums.Where(a => a.Genre.Name == album.Genre.Name).FirstOrDefault() != null)
{
dbEntry.GenreId = context.Albums.Where(a => a.Genre.Name == album.Genre.Name).FirstOrDefault().GenreId;
dbEntry.Genre = context.Albums.Where(a => a.Genre.Name == album.Genre.Name).FirstOrDefault().Genre;
}
else
{
dbEntry.GenreId = album.GenreId;
dbEntry.Genre = album.Genre;
}
dbEntry.Id = album.Id;
dbEntry.ImageData = album.ImageData;
dbEntry.ImageMimeType = album.ImageMimeType;
dbEntry.OrderDetails = album.OrderDetails;
dbEntry.Price = album.Price;
dbEntry.Title = album.Title;
}
}
context.SaveChanges();
}
The controller
...
private IAlbumRepository repository;
public AdminController(IAlbumRepository repo)
{
repository = repo;
}
public ViewResult Index()
{
return View(repository.Albums);
}
public ViewResult Edit(int albumId)
{
Album album = repository.Albums.FirstOrDefault(m => m.Id == albumId);
return View(album);
}
[HttpPost]
public ActionResult Edit(Album album, HttpPostedFileBase image = null)
{
if (ModelState.IsValid)
{
if (image != null)
{
album.ImageMimeType = image.ContentType;
album.ImageData = new byte[image.ContentLength];
image.InputStream.Read(album.ImageData, 0, image.ContentLength);
}
repository.SaveAlbum(album);
TempData["message"] = string.Format("{0} has been saved", album.Title);
return RedirectToAction("Index");
}
else
{
return View(album);
}
}}
The Edit View
#model MusicStore1.Models.Album
#{
ViewBag.Title = "Admit: Edit " + #Model.Title;
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<div>
<div> <br /></div>
<div>
<h3> Edit #Model.Title </h3>
</div>
#using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary()
<div>
#Html.HiddenFor(m => m.Id)
<label> Title </label>
#Html.TextBoxFor(m => m.Title, null, new { #class = "form-control" })
<label> Artist </label>
#Html.TextBoxFor(m => m.Artist.Name, null, new { #class = "form-control" })
<label> Genre </label>
#Html.TextBoxFor(m => m.Genre.Name, null, new { #class = "form-control" })
<label> Price </label>
#Html.TextBoxFor(m => m.Price, null, new { #class = "form-control" })
<div class="form-group">
<div style="position:relative;">
<label> Image </label>
<a class="btn" href="javascript:;">
<input type="file" name="Image" size="40"
style="position:absolute" ;z-index:2;top:0;left:0;filter:alpha(opacity=0);opacity:0;
background-color:transparent; color:transparent;"
onchange='$("#upload-file-info").html($(this).val());' />
</a>
<span class="label label-info" id="upload-file-info"></span>
</div>
#if (Model.ImageData == null)
{
<div class="form-control-static"> No Image</div>
}
else
{
<img class="img-thumbnail" width="150" height="150" src="#Url.Action("GetImage","Album", new { Model.Id })" />
}
</div>
</div>
<div>
<input type="submit" value="save" class="btn btn-success" />
#Html.ActionLink("Cancel and return to List", "Index", null, new
{
#class = "btn btn-info"
})
</div>
}
</div>
The GetImage method
public FileContentResult GetImage(int albumId)
{
Album alb = repository.Albums.FirstOrDefault(p => p.Id == albumId);
if (alb != null)
{
return File(alb.ImageData, alb.ImageMimeType);
}
else
{
return null;
}
}
Every time I try to change something about the album, like its title or price the image I've already saved gets lost after I save the changes. If anyone can help me and figure out what the problem is I'd be really grateful. Thanks in advance!
I think error in this line. You did not pass the albumId parameter correctly from view.
<img class="img-thumbnail" width="150" height="150"
src="#Url.Action("GetImage","Album", new { Model.Id })" />
Resolution:
Use this to pass albumId from view to controller
<img class="img-thumbnail" width="150" height="150"
src="#Url.Action("GetImage","Album", new { albumId = Model.Id })" />
Related
I have httpost activate method which should store the user record(from poll user options model) in database. Activate method display pop-up for user and he chooses one of the choices and submit it. The method purpose is to create record from Poll user options model through the Poll view model.
[HttpPost]
public ActionResult Activate(PollOptionsVM pum)
{
User user = UserService.GetCurrent();
if (ModelState.IsValid)
{
Poll_User_Options model = new Poll_User_Options()
{
poll_id = pum.PollID,
user_id = user.ID,
option_id = pum.OptionID
};
PollUserOptionsService.Create(model); //model
//return RedirectToAction("Index1");
}
return View();
}
And activate view from poll view model. The model state is invalid and record is not created always because pum.PollID and pum.OptionID returns 0 from view. How to create record when user submits credentials
#model test.ViewModels.PollVM
#if (ViewBag.ViewPopup)
{
<div id="PollModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
#using (Html.BeginForm("Activate", "Poll", FormMethod.Post))
{
<h2>Index</h2>
<div class="container">
#Html.HiddenFor(m => m.PollID)
<div class="form-group row">
<label for="polltitle" class="col-lg-2 col-md-2 col-sm-12 col-xs-12 col-form-label col-lg-offset-1 col-md-offset-1">
#Html.DisplayNameFor(m => m.Title)
<span class="text-danger">*</span>
</label>
<div class="col-lg-7 col-md-7 col-sm-12 col-xs-12">
#Html.TextBoxFor(m => m.Title, new { #id = "QuestionTextBody", #class = "form-control ckeditor", disabled = "disabled" })
#Html.ValidationMessageFor(m => m.Title, null, new { #class = "text-danger" })
</div>
</div>
<div class="form-group row">
<table id="myTable" class="order-list">
<thead>
#foreach (var item in Model.PollOptionList)
{
<tr>
<td class="col-sm-7">
#Html.TextBox("OptionTitle", item.Title, new { placeholder = "Enter text here", #class = "form-control", disabled = "disabled" })
#Html.RadioButton("OptionTitle", item.OptionID, new { #class = "custom-control-input"})
</td>
</tr>
}
</thead>
<tbody></tbody>
</table>
</div>
#*<button href="/Poll/Answer" type="submit" value="Submit">Save</button>*#
<button type="submit" value="Submit">Save</button>
</div>
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
}
Here is my PollVM
public class PollVM
{
public int PollID { get; set; }
[Display(Name = "Type")]
[Required]
public int Type { get; set; }
[Display(Name = "Status")]
[Required]
public int Status { get; set; }
[Display(Name = "Title")]
[Required]
public string Title { get; set; }
public DateTime? DateCreated { get; set; }
public DateTime? DateEdited { get; set; }
public List<PollOptionsVM> PollOptionList { get; set; }
public List<PollUserOptionsVM> PollUserOptionsList { get; set; } //added
public int IsSelected { get; set; } //added
public Poll ToModel(PollVM vm)
{
Poll model = new Poll();
model.id = vm.PollID;//added
model.type = vm.Type;
model.status = vm.Status;
model.title = vm.Title;
model.date_created = DateTime.Now;
model.date_edited = model.date_created;
if (vm.PollOptionList != null)
{
foreach(var item in vm.PollOptionList)
{
var option = new Poll_Options();
option.title = item.Title;
option.date_created = DateTime.Now;
option.date_edited = DateTime.Now;
model.Poll_Options.Add(option);
}
}
return model;
}
public Poll ToEditModel(PollVM vm, Poll model)
{
model.type = vm.Type;
model.status = vm.Status;
model.title = vm.Title;
model.date_created = DateTime.Now;
model.date_edited = DateTime.Now;
if(vm.PollOptionList != null)
{
foreach (var item in vm.PollOptionList)
{
var option = new Poll_Options();
option.title = item.Title;
option.date_created = DateTime.Now;
option.date_edited = DateTime.Now;
model.Poll_Options.Add(option);
}
}
return model;
}
public PollVM ToViewModel(Poll model)
{
PollVM ViewModel = new PollVM()
{
PollID = model.id,
Type = model.type,
Status = model.status,
Title = model.title,
DateCreated = model.date_created,
DateEdited = model.date_edited,
PollOptionList = new List<PollOptionsVM>()
};
if (model.Poll_Options.Count != 0)
{
foreach (var option in model.Poll_Options)
{
var optionVM = new PollOptionsVM();
optionVM.OptionID = option.id;
optionVM.PollID = option.poll_id;
optionVM.Title = option.title;
optionVM.DateCreated = DateTime.Now;
optionVM.DateEdited = DateTime.Now;
ViewModel.PollOptionList.Add(optionVM);
}
}
return ViewModel;
}
public List<PollVM> ToViewModelList(List<Poll> polls)
{
List<PollVM> pollList = new List<PollVM>();
foreach(var item in polls)
{
pollList.Add(ToViewModel(item));
}
return pollList;
}
}
get Activate method
public ActionResult Activate()
{
PollVM vm = new PollVM();
Poll poll = PollService.GetPollByStatusActive();
PollVM pvm = new PollVM();
bool b = false;
if (poll != null)
{
pvm = vm.ToViewModel(poll);
b = true;
}
ViewBag.ViewPopup = b;
return PartialView(pvm);
}
I changed your code a bit. Follow these steps. this code work for me. Replace the SetPoll() method with your own data
Change view to this
#foreach (var item in Model.PollOptionList)
{
<tr>
<td class="col-sm-7">
#Html.TextBox("OptionTitle", item.Title, new { placeholder = "Enter text here", #class = "form-control", disabled = "disabled" })
#Html.RadioButton("OptionID", item.OptionID, new { #class = "custom-control-input"})
</td>
</tr>
}
change action to this
public ActionResult Activate()
{
Poll poll = SetPoll();
PollVM pvm = new PollVM();
bool b = false;
if (poll != null)
{
pvm = pvm.ToViewModel(poll);
b = true;
}
ViewBag.ViewPopup = b;
return View(pvm);
}
[HttpPost]
public ActionResult Activate(PollVM pollVM,int OptionID)
{
User user = UserService.GetCurrent();
Poll poll = SetPoll();
bool b = false;
if (poll != null)
{
pollVM = pollVM.ToViewModel(poll);
b = true;
}
Poll_User_Options model = new Poll_User_Options()
{
poll_id = pollVM.PollID,
user_id = user.ID,
option_id = OptionID
};
PollUserOptionsService.Create(model); //model
ViewBag.ViewPopup = b;
return View(pollVM);
}
public Poll SetPoll()
{
Poll poll = new Poll()
{
id = 1,
type = 1,
date_created = DateTime.Now,
title = "poll1",
status = 2,
Poll_Options = new List<Poll_Options>()
{
new Poll_Options(){id=1,title="option1",poll_id=1,date_created=DateTime.Now},
new Poll_Options(){id=2,title="option2",poll_id=1,date_created=DateTime.Now},
new Poll_Options(){id=3,title="option3",poll_id=1,date_created=DateTime.Now},
}
};
return poll;
}
I am using a Dropdownlist in my modal I have it working perfectly with textboxes. I’ve tried changing my Model to multiple different properties (String, Int, SelectListItem). I feel I must be extremely close to getting this to work. I would like my validation message to appear when im using Dropdownlists as well. When the validation message is suppose to appear I get the error message ‘The ViewData item that has the key 'PartVM.IDenteredBy' is of type 'System.Int32' but must be of type 'IEnumerable'.’ Here is my View, Model, and Action.
public class UpdatePartViewModel
{
public int PartID { get; set; }
[Required]
[Display(Name = "Part Number")]
public string PartNumber { get; set; }
//[Required]
[Display(Name = "Entered By")]
public string EnteredBy { get; set; }
public SelectListItem SLIenteredBy { get; set; }
public IEnumerable<SelectListItem> EnteredByOptions { get; set; }
public int IDenteredBy { get; set; }
[Display(Name = "Date Entered")]
public DateTime DateEntered { get; set; }
[Display(Name = "Machine Types")]
public List<int> MachineTypes { get; set; }
//public string MachineTypesString { get; set; }
}
public class FindPartModel
{
[Display(Name = "Entered By")]
public string PNEnteredBy { get; set; }
public IEnumerable<SelectListItem> PNEnteredByOptions { get; set; }
public findPartNumberListAttributes[] info { get; set; }
public List<findPartNumberListAttributes> reportList { get; set; }
public UpdatePartViewModel PartVM { get; set; }
}
//PNControls.cshtml VIEW
#model Messer_PartNumbers.Models.FindPartModel
#{ HtmlHelper.UnobtrusiveJavaScriptEnabled = true; }
#Html.AntiForgeryToken()
#Html.HiddenFor(x => x.PartVM.PartID)
#Html.HiddenFor(x => x.PartVM.PartGroup)
<div class="form-group">
#Html.LabelFor(x =>x.PartVM.PartNumber, htmlAttributes: new { #class="control-label col-3" })
<div class="col-9">
#Html.TextBoxFor(x => x.PartVM.PartNumber, new { #class="form-control", #readonly="readonly" })
#Html.ValidationMessageFor(x => x.PartVM.PartNumber, "", new { #class="text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(x => x.PartVM.EnteredBy, htmlAttributes: new { #class = "control-label col-3" })
<div class="col-9">
#*#Html.TextBoxFor(x => x.PartVM.EnteredBy, new { #class="form-control" })*#
#*#Html.DropDownListFor(x => x.PartVM.SLIenteredBy, Model.PNEnteredByOptions as IEnumerable<SelectListItem>, "Select User", new { #class = "form-control" })*#
#*#Html.DropDownList("DDLenteredBy", Model.PNEnteredByOptions as IEnumerable<SelectListItem>, new { #class="form-control" })*#
#Html.DropDownListFor(x => x.PartVM.IDenteredBy, Model.PNEnteredByOptions as IEnumerable<SelectListItem>, "Select User", new { #class = "form-control" })
#*#Html.ValidationMessageFor(x => x.PartVM.EnteredBy, "", new { #class = "text-danger" })*#
#*#Html.ValidationMessageFor(x => x.PartVM.SLIenteredBy, "", new { #class = "text-danger" })*#
#Html.ValidationMessageFor(x => x.PartVM.IDenteredBy, "", new { #class = "text-danger" })
</div>
</div>
#using (Ajax.BeginForm("PartNumberUpdate", "Parts", new AjaxOptions() { HttpMethod = "POST", UpdateTargetId = "PartNumControls", OnSuccess = "ajaxPartUpdate" }))
{
<div class="modal" id="modalPNUpdate" tabindex="-1" role="dialog" aria-labelledby="lblPNUpdate" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Part Number Details</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" id="PartNumControls">
#Html.Partial("PNControls")
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary" value="Save" />
</div>
</div>
</div>
</div>
}
[HttpPost]
[ValidateAntiForgeryToken]
[HandleError]
public ActionResult PartNumberUpdate(FindPartModel model)
{
if (ModelState.IsValid)
{
var partNumber = context.PartNumbers.Where(x => x.PartNumber1 == model.PartVM.PartNumber).FirstOrDefault();
// Updating the Parts data with the new Models Information.
partNumber.PartNumber1 = model.PartVM.PartNumber;
partNumber.PartGroup = model.PartVM.PartGroup != null ? model.PartVM.PartGroup : partNumber.PartGroup;
partNumber.Last4Number = model.PartVM.Last4Numbers;
//var str = Request.Form["DDLenteredBy"];
//if(model.PartVM.EnteredBy != null)
//{ var enteredByID = context.Employees.Where(e => e.Name == model.PartVM.EnteredBy).Select(x => x.ID).FirstOrDefault();
// partNumber.EnteredBy = enteredByID; }
/* testvar2 = testVar1 != null ? testvar1 : testvar2; || testVar2 = testVar1 ?? testVar2 */
partNumber.EnteredBy = model.PartVM.IDenteredBy;
partNumber.DateEntered = model.PartVM.DateEntered;
/// UPDATE PartNumber Record
context.Entry(partNumber).State = EntityState.Modified;
context.SaveChanges();
ViewBag.ValidMessage = "PartNumber Record Updated";
string returnStr = "refresh";
ModelState.Clear();
return Json(returnStr);
}
TempData["ErrorState"] = "x";
return PartialView("PNControls", model);
}
public ActionResult PNControls()
{
return View(new FindPartModel());
}
I needed to repopulate my Dropdownlists when the ModelState was invalid.
Now my validation with ajax works exactly as expected. I needed this at the end of my PartNumberUpdate Action.
}
/// Populate DropDownLists in Modal to UPDATE fields
var fetcher = new DataFetcher();
model.PNEnteredByOptions = fetcher.EnteredByInfo();
//ViewBag.DDLenteredby = fetcher.EnteredByInfo();
model.PNMachineTypeOptions = fetcher.machineTypeInfo();
model.PNSoftwareTypeOptions = fetcher.softwareTypeInfo();
model.PNManufacturerOptions = fetcher.manufactuerInfo();
model.PNUsageOptions = fetcher.usageInfo();
model.PNUnitsOptions = fetcher.unitsInfo();
TempData["ErrorState"] = "x";
return PartialView("PNControls", model);
}
I have a parent child scenario for getting header detail data. here is my code attached, the problem is when i use a file upload it does not work
Person Model:
public class Person
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Display(Name = "First Name")]
[Required]
[StringLength(255, MinimumLength = 3)]
public string Name { get; set; }
[Display(Name = "Last Name")]
[Required]
[StringLength(255, MinimumLength = 3)]
public string Surname { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Error: Must Choose a Country")]
[Range(1, int.MaxValue, ErrorMessage = "Select a Country")]
public int CountryID { get; set; }
public virtual Country Country { get; set; }
}
Address Model:
public class Address
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Error: Must Choose a City")]
[Range(1, int.MaxValue, ErrorMessage = "Select a City")]
public int CityID { get; set; }
public virtual City City { get; set; }
[Required]
[Display(Name = "Street Address")]
public string Street { get; set; }
[Required]
[DataType(DataType.ImageUrl)]
public string ImageUrl { get; set; }
[NotMapped]
[DataType(DataType.Upload)]
public HttpPostedFileBase ImageUpload { get; set; }
[Required]
[Phone]
public string Phone { get; set; }
public int PersonID { get; set; }
public virtual Person Person { get; set; }
}
PeopleController:
private DataDb db = new DataDb();
// GET: People
public async Task<ActionResult> Index()
{
return View(await db.People.ToListAsync());
}
// GET: People/Details/5
public async Task<ActionResult> Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Person person = await db.People.Where(p => p.Id == id).Include(p => p.Addresses).SingleAsync();
if (person == null)
{
return HttpNotFound();
}
return View(person);
}
// GET: People/Edit/5
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var person = await db.People
.Include(p => p.Addresses)
.Where(p => p.Id == id)
.SingleAsync();
if (person == null)
{
return HttpNotFound();
}
ViewBag.CountryID = new SelectList(db.Country, "CountryID", "CountryName", person.CountryID);
return View(person);
}
// POST: People/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit( Person person)
{
if (ModelState.IsValid)
{
db.Entry(person).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.CountryID = new SelectList(db.Country, "CountryID", "CountryName", person.CountryID);
return View(person);
}
// GET: People/Delete/5
public async Task<ActionResult> Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Person person = await db.People.FindAsync(id);
if (person == null)
{
return HttpNotFound();
}
return View(person);
}
// POST: People/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteConfirmed(int id)
{
Person person = await db.People.FindAsync(id);
db.People.Remove(person);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
Address Controller:
private DataDb db = new DataDb();
public ActionResult Index(int id)
{
ViewBag.PersonID = id;
var addresses = db.Addresses.Where(a => a.PersonID == id).OrderBy(a => a.City.CityName);
return PartialView("_Index", addresses.ToList());
}
[ChildActionOnly]
public ActionResult List(int id)
{
ViewBag.PersonID = id;
var addresses = db.Addresses.Where(a => a.PersonID == id);
return PartialView("_List", addresses.ToList());
}
public ActionResult Create(int PersonID)
{
//Address address = new Address();
//address.PersonID = PersonID;
//FillCity(address);
Address adv = new Address();
adv.PersonID = PersonID;
FillCityModel(adv);
return PartialView("_Create", adv);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Address address, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
int addressID = clsStatic.newAddressID();
address.Id = addressID;
var uploadDir = "~/images";
var imagePath = Path.Combine(Server.MapPath(uploadDir), address.ImageUpload.FileName);
var imageUrl = Path.Combine(uploadDir, address.ImageUpload.FileName);
address.ImageUpload.SaveAs(imagePath);
address.ImageUrl = imageUrl;
db.Addresses.Add(address);
db.SaveChanges();
string url = Url.Action("Index", "Addresses", new { id = address.PersonID });
return Json(new { success = true, url = url });
}
FillCity(address);
return PartialView("_Create", address);
}
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Address address = db.Addresses.Find(id);
if (address == null)
{
return HttpNotFound();
}
//ViewBag.CityID = new SelectList(db.City, "CityID", "CityName", address.CityID);
FillCity(address);
return PartialView("_Edit", address);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Address address )
{
var uploadDir = "~/images";
if (address.ImageUpload != null)
{
var imagePath = Path.Combine(Server.MapPath(uploadDir), address.ImageUpload.FileName);
var imageUrl = Path.Combine(uploadDir, address.ImageUpload.FileName);
address.ImageUpload.SaveAs(imagePath);
address.ImageUrl = imageUrl;
}
if (ModelState.IsValid)
{
db.Entry(address).State = EntityState.Modified;
db.SaveChanges();
string url = Url.Action("Index", "Addresses", new { id = address.PersonID });
return Json(new { success = true, url = url });
}
//var file = Request.Files[0];
//if (file != null && file.ContentLength > 0)
//{
// var fileName = address.Id + Path.GetExtension(file.FileName);
// var path = Path.Combine(Server.MapPath("~/Images/Addresses/"), fileName);
// file.SaveAs(path);
//}
FillCity(address);
//ViewBag.CityID = new SelectList(db.City, "CityID", "CityName", address.CityID);
return PartialView("_Edit", address);
}
private void FillCity(Address address)
{
List<SelectListItem> city = new List<SelectListItem>();
foreach (City item in db.City)
{
if (item.CityID != address.CityID)
city.Add(new SelectListItem { Text = item.CityName, Value = item.CityID.ToString() });
else
city.Add(new SelectListItem { Text = item.CityName, Value = item.CityID.ToString(), Selected = true });
}
ViewBag.CityID = city;
}
private void FillCityModel(Address address)
{
List<SelectListItem> city = new List<SelectListItem>();
foreach (City item in db.City)
{
if (item.CityID != address.CityID)
city.Add(new SelectListItem { Text = item.CityName, Value = item.CityID.ToString() });
else
city.Add(new SelectListItem { Text = item.CityName, Value = item.CityID.ToString(), Selected = true });
}
ViewBag.CityID = city;
}
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Address address = db.Addresses.Find(id);
if (address == null)
{
return HttpNotFound();
}
return PartialView("_Delete", address);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Address address = db.Addresses.Find(id);
db.Addresses.Remove(address);
db.SaveChanges();
string url = Url.Action("Index", "Addresses", new { id = address.PersonID });
return Json(new { success = true, url = url });
}
Here in _Edit View of Address I want to have File Upload Field
#model TestAjax.Models.Address
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Edit Address</h4>
</div>
<div class="modal-body">
#using (Html.BeginForm("Edit", "Addresses", FormMethod.Post,
new { id = "editForm", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.PersonID)
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.CityID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.CityID, (List<System.Web.Mvc.SelectListItem>)ViewBag.CityID, new { #class = "form-control selectpicker" })
#Html.ValidationMessageFor(model => model.CityID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Street, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Street, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Street, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Phone, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Phone, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Phone, "", new { #class = "text-danger" })
</div>
</div>
<div class="editor-field">
#Html.LabelFor(m => m.ImageUpload)
#Html.TextBoxFor(m => m.ImageUpload, new { type = "file" })
</div>
</div>
<button class="btn" type="button" data-dismiss="modal">Cancel</button>
<input class="btn btn-primary" type="submit" value="Save" />
}
</div>
<div class="modal-footer">
Footer
</div>
<script>
$(document).ready(function () {
refill();
});
function refill() {
var id = #Model.CityID;
$('#CityID').val(id);
}
</script>
But when i press the save button in address controller edit action i don't have the file selected.
please help.
Download Source Code
I'm using begincollectionitem component, and when trying to save data is giving error at line db.SaveChanges();. I use MVC 4 e Razor.
This message error:
The operation failed: The relationship could not be changed because
one or more of the foreign-key properties is non-nullable. When a
change is made to a relationship, the related foreign-key property is
set to a null value. If the foreign-key does not support null values,
a new relationship must be defined, the foreign-key property must be
assigned another non-null value, or the unrelated object must be
deleted.
A minha implementação é esta:
Model
public class ProdutoPadrao : IEntidadeBase
{
[Key]
public int ProdutoPadraoID { get; set; }
[Display(Name = "Descrição")]
public string Descricao { get; set; }
[Display(Name = "Detalhe")]
public string Detalhe { get; set; }
public virtual ICollection<ProdutoPadraoCaracteristica> ListaProdutoCaracteristica { get; set; }
}
public class ProdutoPadraoCaracteristica : IEntidadeBase
{
[Key]
public int ProdutoPadraoCaracteristicaID { get; set; }
public int ProdutoPadraoID { get; set; }
public string Descricao { get; set; }
public int TipoCaracteristicaID { get; set; }
[ForeignKey("ProdutoPadraoID")]
public virtual ProdutoPadrao ProdutoPadrao { get; set; }
}
Controller GET
[ControleDeAcesso(TipoAcao.Normal)]
[Authorize]
public ActionResult Detalhar(int id)
{
using (var db = new ERPContext())
{
var produtoPadrao = db.ProdutoPadrao.Include("ListaProdutoCaracteristica").Where(w => w.ProdutoPadraoID == id).ToList().FirstOrDefault();
var retorno = EntidadeBaseExt.ValidarRegistro(produtoPadrao, TipoAcao.Visualizar);
if (retorno != "")
{
TempData["MsgRetornoError"] = retorno;
return RedirectToAction("Index", "Home");
}
ViewBag.ListaCaracteristica = new SelectList(ListagemPadrao.ListaTipoCaracteristica(), "Key", "Texto");
ViewBag.ListaUnidadeMedida = new SelectList(db.UnidadeMedida.ToListERP().Select(l => new ItemLPesquisa { Key = l.UnidadeMedidaID, Texto = l.Descricao }).ToArray(), "Key", "Texto");
return View(produtoPadrao);
}
}
Controller POST
[Authorize]
[HttpPost]
[ControleDeAcesso(TipoAcao.Normal)]
public ActionResult Detalhar(string btnSubmit, ProdutoPadrao model)
{
if (!ModelState.IsValid)
{
return View(model);
}
using (var db = new ERPContext())
{
var produtoPadrao = db.ProdutoPadrao.Include("ListaProdutoCaracteristica").Where(w => w.ProdutoPadraoID == model.ProdutoPadraoID).ToList().FirstOrDefault();
var retorno = FlexGestor.Helpers.EntidadeBaseExt.ValidarRegistro(produtoPadrao, TipoAcao.Gravar);
if (retorno != "")
{
TempData["MsgRetornoError"] = retorno;
return RedirectToAction("Index", "Home");
}
if (btnSubmit != "Excluir")
UpdateModel(produtoPadrao);
FlexGestor.Helpers.EntidadeBaseExt.AtribuirValores(produtoPadrao, btnSubmit);
db.Entry(produtoPadrao).State = EntityState.Modified;
db.SaveChanges();
if (btnSubmit == "Excluir")
return RedirectToAction("Index", controller);
return RedirectToAction("Detalhar", controller, new { id = model.ProdutoPadraoID });
}
}
View
#model FlexGestor.Models.ProdutoPadrao
#using (Html.BeginForm())
{
<div class="row">
#Html.TituloPagina("Visualizando Produto Padrão", "Clique para abrir a ajuda", "#help_produtoPadrao")
#Html.HiddenFor(m => m.ProdutoPadraoID)
<div class="col-md-12">
#Html.LabelFor(m => m.Descricao) #Html.ValidationMessageFor(m => m.Descricao)
#Html.TextBoxFor(m => m.Descricao, new { #class = "form-control" })
</div>
<div class="col-md-12">
#Html.LabelFor(m => m.Detalhe) #Html.ValidationMessageFor(m => m.Detalhe)
#Html.TextAreaFor(m => m.Detalhe, new { #class = "form-control", #rows = "4" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ListaProdutoCaracteristica)
<div class="controls">
<ul id="PhonesEditor" style="list-style-type: none">
#if (Model.ListaProdutoCaracteristica != null)
{
foreach (var item in Model.ListaProdutoCaracteristica)
{
Html.RenderPartial("_CustomerPhonesEditor", item);
}
}
</ul>
</div>
<p><a id="addAnother" class="small-button">AddPhone</a></p>
</div>
<div class="row">
<div class="col-md-12">
#Html.BotaoTelaDetalhar()
</div>
</div>
}
View Detail
#model FlexGestor.Models.ProdutoPadraoCaracteristica
#using (Html.BeginCollectionItem("ListaProdutoCaracteristica"))
{
#Html.HiddenFor(m => m.ProdutoPadraoID)
#Html.HiddenFor(m => m.ProdutoPadraoCaracteristicaID)
<div class="col-md-3">
#Html.LabelFor(m => m.TipoCaracteristicaID) #Html.ValidationMessageFor(m => m.TipoCaracteristicaID)
#Html.DropDownList("TipoCaracteristicaID", (SelectList)ViewBag.ListaCaracteristica, String.Empty,
new { #class = "form-control" })
</div>
<div class="col-md-9">
#Html.LabelFor(m => m.Descricao) #Html.ValidationMessageFor(m => m.Descricao)
#Html.TextBoxFor(m => m.Descricao, new { #class = "form-control" })
</div>
<div class="form-group">
<div class="controls">
<a onclick="$(this).parent().parent().parent().remove();" class="small-button" style="float: left;">Delete</a>
</div>
</div>
}
The below line is causing the problem
model.ListaProdutoCaracteristica = null;
It would cause the below property to be null, but it is not a nullable type
public int ProdutoPadraoID { get; set; }
If you want to be able to orphan records in this way, then you need to change it to a nullable int:
public int? ProdutoPadraoID { get; set; }
In my view the DropDownList shows the correct fields but when I select one in "edit or create" the field will be saved/modified as NULL. When debugging I can see that the new value is not send. I think there is a mismatch between ID and SurveyID...
View:
#model Project_ASP_2012.Models.QuestionGroup
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>QuestionGroup</legend>
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.SurveyID, "Survey")
</div>
<div class="editor-field">
#Html.DropDownList("Id", String.Empty)
#Html.ValidationMessageFor(model => model.SurveyID)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Model:
public class Survey : IEntity
{
[Key]
[Display(Name = "SurveyID")]
public int ID { get; set; }
[Required(ErrorMessage = "Survey title is required.")]
[Display(Name = "Survey Title")]
[MaxLength(20, ErrorMessage = "Title cannot be longer than 20 characters.")]
public string Title { get; set; }
[MaxLength(50, ErrorMessage = "Description cannot be longer than 50 characters.")]
public string Description { get; set; }
public virtual ICollection<QuestionGroup> QuestionGroups { get; set; }
}
public class QuestionGroup : IEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[MaxLength(50, ErrorMessage = "Description cannot be longer than 50 characters.")]
public string Description { get; set; }
[Display(Name = "SurveyID")]
public int? SurveyID { get; set; }
public virtual Survey Survey { get; set; }
}
Controller:
public ActionResult Edit(int id)
{
QuestionGroup questiongroup = unitOfWork.QuestionGroupRepository.GetById(id);
if (questiongroup == null)
{
return HttpNotFound();
}
PopulateSurveysDropDownList(questiongroup.SurveyID);
return View(questiongroup);
}
//
// POST: /QuestionGroup/Edit/5
[HttpPost]
public ActionResult Edit(QuestionGroup questiongroup)
{
try
{
if (ModelState.IsValid)
{
unitOfWork.UoWContext.Entry(questiongroup).State = EntityState.Modified;
unitOfWork.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
PopulateSurveysDropDownList(questiongroup.SurveyID);
return View(questiongroup);
}
private void PopulateSurveysDropDownList(object selectedSurvey = null)
{
var surveyQuery = unitOfWork.SurveyRepository.Get(
orderBy: q => q.OrderBy(d => d.Title));
ViewBag.Id = new SelectList(surveyQuery, "Id", "Title", selectedSurvey);
}
In your view you have dropdown for Id instead of SurveyId. Additionaly you have ID twice - in dropdown and in hidden field.
<div class="editor-field">
#Html.DropDownList("Id", String.Empty)
#Html.ValidationMessageFor(model => model.SurveyID)
</div>
Try changing:
private void PopulateSurveysDropDownList(object selectedSurvey = null)
{
var surveyQuery = unitOfWork.SurveyRepository.Get(
orderBy: q => q.OrderBy(d => d.Title));
ViewBag.Id = new SelectList(surveyQuery, "Id", "Title", selectedSurvey);
}
....
<div class="editor-field">
#Html.DropDownList("Id", String.Empty)
#Html.ValidationMessageFor(model => model.SurveyID)
</div>
To:
private void PopulateSurveysDropDownList(object selectedSurvey = null)
{
var surveyQuery = unitOfWork.SurveyRepository.Get(
orderBy: q => q.OrderBy(d => d.Title));
//don't provide the select value here. you will bind to it in your view
ViewBag.SurveySelectList = new SelectList(surveyQuery, "Id", "Title");
}
....
<div class="editor-field">
//selected value will be whatever SurveyID is on your model.
#Html.DropDownListFor(model => model.SurveyID, ViewBag.SurveySelectList, String.Empty)
#Html.ValidationMessageFor(model => model.SurveyID)
</div>
Hope that helps.