I am using autocomplete from JQueryUIHelpers in my Asp.Net MVC project with EF6.
Model structure:
public class Employee
{
[Key]
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string SecondName { get; set; }
[NotMapped]
public string FullName => FirstName + " " + SecondName;
public bool IsDriver { get; set; } = false;
public virtual ICollection<Delivery> Deliveries { get; set; }
}
public class Delivery
{
[Key]
public int Id { get; set; }
[Required]
public Employee Driver { get; set; }
public virtual ICollection<EggsMag> Eggs { get; set; }
}
EmployeeController:
public ActionResult Drivers(string term)
{
var drivers = _rep.GetAll(e => e.IsDriver && (e.FirstName.StartsWith(term) || e.SecondName.StartsWith(term)));
return Json((from d in drivers select new { label = d.FullName, value = d.Id }).ToList(), JsonRequestBehavior.AllowGet);
}
DeliveriesController:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,DateOfDelivery,Driver")] Delivery delivery)
{
if (ModelState.IsValid)
{
_rep.Save(delivery);
return RedirectToAction("Index");
}
return View(delivery);
}
View:
#Html.JQueryUI().AutocompleteFor(m => m.Driver.Id, Url.Action("Drivers", "Employees"), "DriverId", null)
Problem Description:
Autocomplete is working correctly but when in Edit view I send POST request I receive all the data, but ModelState.IsValid is false.
The error shows that fields of FirstName and SecondName are empty which is true because I sent just Id of existing Driver, not whole object.
Is there a way to fix it?
Maybe some way to change validation to not check inner model(Driver) fields except Driver.Id existence.
Related
Upon my post ActionResult Edit, I am receiving an error. System.Web.Mvc.WebViewPage<TModel>.Model.get returned null
My controller:
[HttpPost]
public ActionResult Edit(editRequestViewModel _editRequestViewModel, int id)
{
try
{
if (ModelState.IsValid)
{
using (var db = new HelpDeskContext())
{
db.Entry(_editRequestViewModel.userRequest).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Digest",new { id = _editRequestViewModel.userRequest.ID });
}
}
else
return View();
}
catch (Exception ex)
{
return View("Error", new HandleErrorInfo(ex, "Change", "Browse"));
}
}
My View includes this for the models field to bind:
#Html.DropDownListFor(model => model.userRequest.forApplication, Model.Applications, "Select Application", new { #class = "form-control" })
My Model has the field as nullable int?:
public int? forApplication { get; set; }
It seems to update the other fields in the model with this field just fine on POST. When the request is first created and saved to the DB, it saves fine in that field when its null. It seems to me that nullable should be OK as a value when its posting (Edit ActionResult)?
EDIT: This is my GET Method that populates the View Model which is passed in to the POST.
public ActionResult Edit(int id)
{
try
{
if (ModelState.IsValid)
{
using (var db = new HelpDeskContext())
{
var query = (from m in db.Requests
where m.ID == id
select new editRequestViewModel()
{
Applications = (from r in db.Applications
select new SelectListItem(){
Text = r.Name,
Value = r.ID.ToString()
}).ToList(),
closeReasons = (from r in db.CloseReasons
select new SelectListItem()
{
Text = r.Name,
Value = r.ID.ToString()
}).ToList(),
userRequest = m
}).FirstOrDefault();
return View(query);
}
}
else
return View();
}
catch (Exception ex)
{
return View("Error", new HandleErrorInfo(ex, "Change", "Browse"));
}
}
And my View has #model HelpDeskSolution.ViewModels.editRequestViewModel
EDIT 2: ViewModel and Model
namespace HelpDeskSolution.Models
{
public class Request
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity), Key()]
public int ID { get; set; }
[Required]
[StringLength(99, MinimumLength = 3)]
public string Title { get; set; }
[StringLength(1000, MinimumLength = 1)]
[Required]
public string Description { get; set; }
[Required]
[Display(Name = "Submit Date")]
public DateTime SubmitDate { get; set; }
public DateTime? CloseDate { get; set; }
[Required]
[StringLength(30)]
public string Author { get; set; }
[Required]
[StringLength(30)]
public string AuthDept { get; set; }
[StringLength(30)]
[Display(Prompt = "Text at top of Epicor Screen...(Optional)")]
public string Module { get; set; }
public int Urgency { get; set; }
[StringLength(30)]
public string Type { get; set; }
public int Status { get; set; }
[StringLength(30)]
[Display(Name = "Request For")]
public string RequestFor { get; set; }
[Required]
public bool Closed { get; set; }
[StringLength(30)]
[Display(Name = "Assign To")]
public string AssignedTo { get; set; }
[Display(Name = "Application")]
public int? forApplication { get; set; }
public int? closeReason { get; set; }
public string ClosedBy { get; set; }
[Display(Name = "ID")]
public int? duplicateOf { get; set; }
}
}
Model:
namespace HelpDeskSolution.ViewModels
{
public class editRequestViewModel
{
public Request userRequest { get; set; }
public List<SelectListItem> Applications { get; set; }
public List<SelectListItem> closeReasons { get; set; }
}
}
Ended up solving this with the direction of #StephenMuecke. The reason I was getting the exception is because upon the return View() in the else portion of the post action, it was attempting to return the view without Applications list, as Stephen said. However that led me to realize that there was first a problem with the Model State, hence why it was even going to the else in the first place. I had another field that was being passed null when it wasnt a nullable type.
I simply changed the type to int? and added a migration and the Action result is A'Okay now.
Is there any way to somehow combine the data from two models and THEN map them both to the same viewModel in the context of an edit action?
I have never had to update several tables at once in an edit action in ASP.NET MVC with Entity Framework 6.1.3. This is the layout:
I have a DB table called "Address" which has fields for StreetNumber, StreetName, City, State, ZipCode. It has a one-to-one relationship with another table called Bars. As in, a bar can only have one address and one address can only have one bar.
Because I am storing this data in two separate tables, I am having a very difficult time trying to successfully implement an Edit action which takes data from one form (BarForm) and should update both the Bar and Address database tables. See my code:
BarController
public ActionResult Edit(int id)
{
var bar = _context.Bars.SingleOrDefault(m => m.Id == id);
var address = _context.Addresses.SingleOrDefault(a => a.BarId == id);
//Make sure that the id actually exists:
if (bar == null)
{
return HttpNotFound();
}
var viewModel = Mapper.Map<Bar, BarFormViewModel>(bar, new BarFormViewModel());
if (address == null)
{
address = new Address();
}
Mapper.Map<Address, BarFormViewModel>(address, viewModel);
viewModel.IsNew = false;
return View("BarForm", viewModel);
}
[ValidateAntiForgeryToken]
public ActionResult Save(BarFormViewModel bar)
{
if (!ModelState.IsValid)
{
var viewModel = Mapper.Map<BarFormViewModel, BarFormViewModel>(bar, new BarFormViewModel());
viewModel.IsNew = false;
return View("BarForm", viewModel);
}
if (bar.Id == 0)
{
var newbar = Mapper.Map<BarFormViewModel, Bar>(bar);
newbar.LastUpdated = DateTime.UtcNow;
_context.Bars.Add(newbar);
var addressToAdd = Mapper.Map<BarFormViewModel, Address>(bar);
_context.Addresses.Add(addressToAdd);
}
else
{
var barInDb = _context.Bars.Single(b => b.Id == bar.Id);
var addressInDb = _context.Addresses.Single(a => a.BarId == bar.Id);
Mapper.Map<BarFormViewModel, Bar>(bar, barInDb);
Mapper.Map<BarFormViewModel, Address>(bar, addressInDb);
}
_context.SaveChanges();
return RedirectToAction("Index", "Bar");
}
Domain Models:
public class Bar
{
public int Id { get; set; }
public string Name { get; set; }
[Required]
public string GooglePlaceId { get; set; }
public string SundayDiscounts { get; set; }
public string MondayDiscounts { get; set; }
public string TuesdayDiscounts { get; set; }
public string WednesdayDiscounts { get; set; }
public string ThursdayDiscounts { get; set; }
public string FridayDiscounts { get; set; }
public string SaturdayDiscounts { get; set; }
[Display(Name = "Last Updated")]
public DateTime LastUpdated { get; set; }
}
public class Address
{
public int Id { get; set; }
public int? Number { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
public string State { get; set; }
[Required]
public int ZipCode { get; set; }
public Bar Bar { get; set; }
public int BarId { get; set; }
}
View Model which includes both Address and Bar properties:
{
public class BarFormViewModel
{
public int? Id { get; set; }
public string Name { get; set; }
[Required]
[Display(Name = "Google Place ID")]
public string GooglePlaceId { get; set; }
[Display(Name = "Sunday Happy Hour Info:")]
public string SundayDiscounts { get; set; }
[Display(Name = "Monday Happy Hour Info:")]
public string MondayDiscounts { get; set; }
[Display(Name = "Tuesday Happy Hour Info:")]
public string TuesdayDiscounts { get; set; }
[Display(Name = "Wednesday Happy Hour Info:")]
public string WednesdayDiscounts { get; set; }
[Display(Name = "Thursday Happy Hour Info:")]
public string ThursdayDiscounts { get; set; }
[Display(Name = "Friday Happy Hour Info:")]
public string FridayDiscounts { get; set; }
[Display(Name = "Saturday Happy Hour Info:")]
public string SaturdayDiscounts { get; set; }
[Display(Name = "Last Updated")]
public DateTime? LastUpdated { get; set; }
//Address Model Info
public Address Address { get; set; }
public int? AddressId { get; set; }
[RegularExpression("([1-9][0-9]*)", ErrorMessage = "Must be a number")]
public int? Number { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
public string State { get; set; }
[Required]
public int? ZipCode { get; set; }
public bool IsNew { get; set; }
}
The problem here is that I am getting an empty AddressId with this setup, which is causing an exception when the Save action gets run. This is because the BarForm view is getting passed a ViewModel which has been mapped from a Bar object and the Bar domain model actually has no Address information in it, since it is not the Address model/table.
Is there any way to somehow combine the data from both the Address and Bar models and THEN map them both to the same viewModel?
I keep getting a Sequence Contains no Elements error for this line in the Save action:
var addressInDb = _context.Addresses.Single(a => a.Id == bar.AddressId);
I also tried:
var addressInDb = _context.Addresses.Single(a => a.BarId == bar.Id);
Neither work. I understand what the error is saying and have also checked the actual HTML for my hidden Addressid field and it is blank... See code in my BarForm View:
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.AddressId)
#Html.AntiForgeryToken()
Remove the new BarFormViewModel() as the second parameter in your mapping calls as it is not necessary.
In your post action, inside your if statement that checks if the ModelState is valid and if bar.Id == 0, bar is already a view model, so no need to mapping.
And when you create your AutoMapper mapping, you must create a custom property mapping because the Address.Id property will not map automatically to the AddressId property as the name is not the same.
AutoMapper.Mapper.CreateMap<Address, BarFormViewModel>()
.ForMember(dest => dest.AddressId, o => o.MapFrom(source => source.Id));
And then do the same for the inverse mapping.
I have my ViewModel, and I have my controller to display from the ViewModel correctly, however I'm not sure how I would make the ViewModel editable, as to send the edited data back to the Model. I only want to edit the OrderArchiveViewModel, not the details
ViewModel;
public class OrderArchiveViewModel
{
public int OrderId { get; set; }
public System.DateTime OrderDate { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
public decimal Total { get; set; }
public bool HasBeenShipped { get; set; }
public List<OrderDetailArchive> Details { get; set; }
}
public class OrderDetailArchive
{
public string Title { get; set; }
public string Colour { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
}
Controller;
[Authorize(Roles = "Administrator")]
public ActionResult Index()
{
List<T_shirt_Company_v3.ViewModels.OrderArchiveViewModel> list = (from o in new TshirtStoreDB().Orders
.OrderBy(o => o.OrderDate)
.Select(o => new OrderArchiveViewModel()
{
OrderId = o.OrderId,
Address = o.Address,
FirstName = o.FirstName,
LastName = o.LastName,
City = o.City,
OrderDate = o.OrderDate,
PostalCode = o.PostalCode,
Total = o.Total,
HasBeenShipped = o.HasBeenShipped,
Details = (from d in o.OrderDetails
select new OrderDetailArchive
{
Colour = d.Product.Colour,
Quantity = d.Quantity,
Title = d.Product.Title,
UnitPrice = d.UnitPrice
}).ToList()
}).ToList()select o).ToList();
ViewBag.ShippedMessage = list.Where(w => w.HasBeenShipped).Any() ? "Order has been shipped" : "Order is being processed";
return View(list);
}
I can suggest you to make an another two actions.
public ActionResult Edit(int id)
where you will get the Order by it's Id, map to ViewModel and pass it to the view where you will have textboxes for editing. Create another one Action for accepting post request with updated model:
[HttpPost]
public ActionResult Edit(OrderArchiveViewModel model)
When the the edit page is submitted you will have a updated model with the new data, then find your model in database by Id and update the properties.
Can u send the code of your View to get more clarification?
The already given answer could be done by redirect to a page for editing purpose.
Do you want to show the Editing fields above the Grid?
For this purpose, you can add New ViewModel like
public class NewViewModel
{
public OrderArchiveViewModel OrderArchiveViewModel { get; set; }
public List<OrderArchiveViewModel> OrderArchiveViewModelList { get; set; }
}
And you can send data using this NewViewModel to View containing both editable OrderArchiveViewModel depending on the Id and also the List of OrderArchiveViewModel by assigning the list present in Index() action.
This a simple project where users can search for job postings by area of expertise. The relationship between Areas and Postings are Many-to-many. I seem to be able to get to the very last part of retrieving the correctly filtered list, but getting back into the view model keeps giving me different errors:
ViewModel:
public class AreaOfertasViewModel
{
public Oferta UnaOferta { get; set; }
public SelectList AreasTrabajo { get; set; }
public IEnumerable<Oferta> Ofertas { get; set; }
public int idArea { get; set; }
public AreaOfertasViewModel()
{
this.UnaOferta = UnaOferta;
this.Ofertas = new List<Oferta>();
cargarAreas();
}
private void cargarAreas()
{
PostulaOfertaContext db = new PostulaOfertaContext();
this.AreasTrabajo = new SelectList(db.Areas, "areaId", "Area");
}
}
}
Controller:
public ActionResult SearchXArea()
{
return View(new AreaOfertasViewModel());
}
[HttpPost]
public ActionResult SearchXArea(AreaOfertasViewModel aovm)
{
int id = aovm.idArea;
PostulaOfertaContext db = new PostulaOfertaContext();
var area = db.Areas.Where(c => c.areaId == id);
var ofertas = from c in db.Ofertas.Where(r => r.AreaTrabajo == area)
select c;
aovm.Ofertas = (IEnumerable<Oferta>)ofertas.ToList();
return View(aovm);
}
The line giving me issues is
aovm.Ofertas = (IEnumerable)ofertas.ToList();
I've tried List<> for Ofertas, and I've tried leaving it as .ToList() without casting, and casting it as different things, but it gives me errors about not being able to cast it, and "Cannot compare elements of type 'System.Collections.Generic.List`1'. Only primitive types, enumeration types and entity types are supported."
What's the solution here?
Model for AreaTrabajo:
public class AreaTrabajo
{
[Key]
public int areaId { get; set; }
public string Area { get; set; }
public virtual List<Oferta> oferta { get; set; }
}
Model for Oferta:
public class Oferta
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Titulo { get; set; }
[Required]
public DateTime Vencimiento { get; set; }
[Required]
public string Cargo { get; set; }
[Required]
public int HorarioComienzo { get; set; }
[Required]
public int HorarioFin { get; set; }
[Required]
public string DescripcionTareas { get; set; }
public int Remuneracion { get; set; }
[Required]
public int RangoEdadMin { get; set; }
[Required]
public int RangoEdadMax { get; set; }
public string TipoFormacion { get; set; }
public string Idiomas { get; set; }
public string Competencias { get; set; }
public string OtrosEstudios { get; set; }
public string Estado { get; set; }
public virtual List<AreaTrabajo> AreaTrabajo { get; set; }
public virtual TipoContrato TipoContrato { get; set; }
public virtual Empresa Empresa { get; set; }
public virtual List<Postulante> Postulantes { get; set; }
}
Answer
[HttpPost]
public ActionResult SearchXArea(AreaOfertasViewModel aovm)
{
int id = aovm.idArea;
PostulaOfertaContext db = new PostulaOfertaContext();
var area = db.Areas.Where(c => c.areaId == id).FirstOrDefault();
var ofertas = db.Ofertas.Where(s => s.AreaTrabajo.All(e => e.areaId == area.areaId)).ToList();
aovm.Ofertas = ofertas;
return View(aovm);
}
Sorry if my question wasn't clear enough. I needed to filter out from the many-to-many relationship, and this solved it.
You are getting an error because the actual sql is executed when you call tolist(). The error is in your sql because you are comparing AreaTrabago to a list.
[HttpPost]
public ActionResult SearchXArea(AreaOfertasViewModel aovm)
{
int id = aovm.idArea;
PostulaOfertaContext db = new PostulaOfertaContext();
var area = db.Areas.Where(c => c.areaId == id).FirstOrDefault();
var ofertas = db.Ofertas.Where(s => s.AreaTrabajo.All(e => e.areaId == area.areaId)).ToList();
aovm.Ofertas = ofertas;
return View(aovm);
}
Sorry if my question wasn't clear enough. I couldn't get the many-to-many relationship, and this solved the filtering problem perfectly.
I am new to the MVC and EF world. I am targeting MVC 4 EF 5 using code first.
I am looking for the best practice for editing two related models using one view. For simplicity I have the following two Models:
namespace AddressBook.Models
{
public class Contact
{
public int ID { get; set; }
public string First_Name { get; set; }
public string Last_Name { get; set; }
public List<PhoneNumber> PhoneNumbers { get; set; }
}
}
and
namespace AddressBook.Models
{
public class PhoneNumber
{
public int ID { get; set; }
public string Number { get; set; }
public bool Primary { get; set; }
}
}
with the following context:
using System.Data.Entity;
namespace AddressBook.Models
{
public class DataContext : DbContext
{
public DbSet<Contact> Contacts { get; set; }
public DbSet<PhoneNumber> PhoneNumbers { get; set; }
}
}
The relationship between the Contact and PhoneNumber is one to many, However I would like to be able to edit the first_name, last_name and Number when the Primary is set to true, so we would be editing only one phone number per contact record.
I have seen similar posts that point to using a ViewModel but the only examples of viewmodels I have seen are when used instead of the viewbag when passing the information for a dropdown.
I guess I have a few questions:
would the ViewModel look like below?
public class ContactPrimaryNumberViewModel
{
public Contact ContactToEdit {get; set;}
public PhoneNumber PhoneNumberToEdit {get;set;}
}
what would the edit(post) and edit(get) look like?
Any help would be appreciated to help me wrap my head around this ...
here is the Edit(get) modified to support if contact does not have phone number associated
' // GET: /Contact/Edit/5
public ActionResult Edit(int id = 0)
{
ContactPrimaryNumberViewModel ContactPrimaryNumber = (from pn in db.PhoneNumbers
where pn.ContactID == id && pn.Primary == true
select new ContactPrimaryNumberViewModel { ContactID = pn.ContactID, First_Name = pn.Contact.First_Name, Last_Name = pn.Contact.Last_Name, Number = pn.Number }).SingleOrDefault();
if (ContactPrimaryNumber == null)
{
ContactPrimaryNumber = (from c in db.Contacts
where c.ID == id
select new ContactPrimaryNumberViewModel { ContactID = c.ID, First_Name = c.First_Name, Last_Name = c.Last_Name, Number = null }).Single();
}
return View(ContactPrimaryNumber);
}'
so the final solution after everyones help is:
the models:
public class PhoneNumber
{
public int ID { get; set; }
public string Number { get; set; }
public bool Primary { get; set; }
[Required]
public int ContactID { get; set; }
public Contact Contact { get; set; }
}
public class Contact
{
public int ID { get; set; }
public string First_Name { get; set; }
public string Last_Name { get; set; }
public List<PhoneNumber> PhoneNumbers { get; set; }
}
The controler edit(get and post)
// GET: /Contact/Edit/5
public ActionResult Edit(int id = 0)
{
ContactPrimaryNumberViewModel ContactPrimaryNumber = (from c in db.Contacts
join pn in db.PhoneNumbers
on c.ID equals pn.ContactID into outer
from _pn in outer.Where(p => p.Primary ==true).DefaultIfEmpty()
where c.ID == id
select new ContactPrimaryNumberViewModel { ContactID = c.ID, First_Name = c.First_Name, Last_Name = c.Last_Name, Number = ((_pn == null) ? "" : _pn.Number) }).FirstOrDefault();
if (ContactPrimaryNumber == null)
{
return HttpNotFound();
}
return View(ContactPrimaryNumber);
}
// POST: /Contact/Edit/5
[HttpPost]
public ActionResult Edit(ContactPrimaryNumberViewModel ContactPrimaryNumber)
{
Contact c = db.Contacts.Find(ContactPrimaryNumber.ContactID);
PhoneNumber pn = db.PhoneNumbers.FirstOrDefault(x => x.ContactID == ContactPrimaryNumber.ContactID && x.Primary == true);
if (ModelState.IsValid)
{
c.First_Name = ContactPrimaryNumber.First_Name;
c.Last_Name = ContactPrimaryNumber.Last_Name;
if (pn == null) //if there is no phone number associated with the contact in the DB
{
if (!String.IsNullOrEmpty(ContactPrimaryNumber.Number))
{
//Add a new phonenumber in the database
PhoneNumber Px = new PhoneNumber();
Px.ContactID = ContactPrimaryNumber.ContactID;
Px.Number = ContactPrimaryNumber.Number;
Px.Primary = true;
db.PhoneNumbers.Add(Px);
}
}
else //if there is a phone number associated with the contactin the DB
{
if (String.IsNullOrEmpty(ContactPrimaryNumber.Number))
{
//delete the existing number
db.PhoneNumbers.Remove(pn);
}
else
{
//modify the existing number
pn.Number = ContactPrimaryNumber.Number;
}
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(c);
}
and the viewmodel
public class ContactPrimaryNumberViewModel
{
public int ContactID { get; set; }
public string First_Name { get; set; }
public string Last_Name { get; set; }
public string Number { get; set; }
}
thanks again for your help
I think your view model should look like this:
public class ContactPrimaryNumberViewModel
{
public int ID { get; set; }
public string First_Name { get; set; }
public string Last_Name { get; set; }
public string Number { get; set; }
}
And your update would look something like:
Contact c = context.Contacts.Find(id);
PhoneNumber p = context.PhoneNumbers
.FirstOrDefault(x => x.id == id && x.Primary == true);
//validate input
//update as necessary
//SaveChanges() etc...
from your comment - you new up the model class ContactPrimaryNumberViewModel:
var ContactPrimaryNumber =
from pn in db.PhoneNumbers
where pn.ContactID == id && pn.Primary == true
select new ContactPrimaryNumberViewModel() {
ContactID = pn.ContactID,
First_Name = pn.Contact.First_Name,
Last_Name = pn.Contact.Last_Name,
Number = pn.Number
};
Okay, try this:
PhoneNumber
public class PhoneNumber
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Number { get; set; }
public bool Primary { get; set; }
[ForeignKey("Contact"), DatabaseGenerated(DatabaseGeneratedOption.None)]
public int? ContactId { get; set; }
public virtual Contact Contact { get; set; }
}
Contact
public class Contact
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<PhoneNumber> PhoneNumbers { get; set; }
}
SaveContact: depending on how you have set up your Repositories or Ef class. This can either go in your EfRepository implemention or your EfDb class.
public void SavePlayer(Contact contact)
{
using (var context = new EfDb())
{
if (contact.ContactId == 0)
{
context.Contacts.Add(contact);
}
else if (contact.ContactId > 0)
{
var currentContact = context.Contacts
.Include(c => c.PhoneNumber)
.Single(c => c.ContactId== contact.ContactId);
context.Entry(currentContact).CurrentValues.SetValues(contact);
currentContact.PhoneNumber= contact.PhoneNumber;
}
context.SaveChanges();
}
}
Edit action
[HttpGet]
public ActionResult Edit(int id)
{
var contact= _dataSource.Contacts.FirstOrDefault(c => c.Id == id);
return View(player);
}
[HttpPost]
public ActionResult Edit(Contact contact)
{
try
{
if (ModelState.IsValid)
{
_dataSource.SaveContact(contact);
return RedirectToAction("About", "Home");
}
}
catch (Exception)
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
return View(contact);
}
Views
In your Contact View Folder add EditorTemplates folder. Then Scaffold a Create Strongly Typed PhoneNumber Partial View to this folder and name it PhoneNumber like its model.
Scaffold a Create Strongly Typed Contact View name it Create
Then add #Html.EditorFor(model => model.PhoneNumber) to the master Create View.