-1

I've got an edit page that is being populated from a ViewModel. This ViewModel takes in items from a couple of models (Participant, Gender, Country):

ViewModel

namespace MVCManageParticipants.Models
{
    public class ParticipantDetailsViewModel
    {
        public int Id { get; set; }
        public int SiteId { get; set; }
        public int Status { get; set; }
        public string Gender { get; set; }
        public string Title { get; set; }
        public string Name { get; set; }
        public string City { get; set; }
        public int CountryId { get; set; }
        public string Country { get; set; }
        public string Postcode { get; set; }
        public string Telephone { get; set; }
        public string Notes { get; set; }

        public IEnumerable<Country> Countries { get; set; }
    }
}

The IEnumerable Countries beings back a full list of countries and fills a dropdown list with the data from a database (this is something I'm wanting to extend on with City, Gender, Status but need to get one working first).

Side question: is how I am doing this the accepted way to fill a dropdown list on the View from a database?

The page populates fine on the [HttpGet] and sends back the ViewModel to the view.

[HttpGet] Controller

var model = (from p in _db.Participants
             where p.Id == id
             select new ParticipantDetailsViewModel
             {
                Id = p.Id,
                SiteId = p.SiteId,
                Status = p.Status,
                Gender = p.Gender.Name,
                Title = p.Title,
                Name = p.Name,
                City = p.City.Name,
                Country = p.Country.PrettyName,
                CountryId = p.Country.Id,
                Postcode = p.Postcode,
                Telephone = p.Telephone,
                Notes = p.Notes,
                Countries = _db.Countrys.ToList()
      }).FirstOrDefault();

[HttpPost] controller

public ActionResult Edit(ParticipantDetailsViewModel viewModel)
        {
            if (ModelState.IsValid)
            {
                _db.Entry(viewModel).State = EntityState.Modified;
                _db.SaveChanges();
                return RedirectToAction("Index", new { id = viewModel.Id });
            }
            return View(viewModel);
        }

Which is giving me an error on the line _db.Entry(viewModel).State = EntityState.Modified;:

An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code

Additional information: The entity type ParticipantDetailsViewModel is not part of the model for the current context.

Participant Model

public class Participant
    {
        public int Id { get; set; }
        public int SiteId { get; set; }
        public int Status { get; set; }
        public Gender Gender { get; set; }
        public string Title { get; set; }
        public string Name { get; set; }
        public City City { get; set; }
        public Country Country { get; set; }
        public string Postcode { get; set; }
        public string Telephone { get; set; }
        public string Notes { get; set; }
    }

I this because I am trying to update the ViewModel rather than the Participant model? Should I be creating a new Participant object and updating with the incoming data that way?

jonnow
  • 814
  • 2
  • 10
  • 19
  • You need to get the `Participant` data model from the database based on the `Id` and update it properties from the view model, then save the data model. –  May 12 '17 at 09:07
  • Your `Countries` should also be `IEnumerable` and you need to repopulate that property in the POST method before you return the view (refer [The model item passed into the dictionary is of type .. but this dictionary requires a model item of type](http://stackoverflow.com/questions/40373595/the-model-item-passed-into-the-dictionary-is-of-type-but-this-dictionary-requ)) –  May 12 '17 at 09:09

1 Answers1

1

ParticipantDetailsViewModel is not part of the dbcontext you need to get the Participant object from the database with the id and update it with informations from the viewModel :

public ActionResult Edit(ParticipantDetailsViewModel viewModel)
{
      if (ModelState.IsValid)
      {
           var participant = _db.Participants.FirstOrDefault(p => p.Id == viewModel.Id);

           //set all properties whith new values
           participant.SiteId = viewModel.SiteId

           _db.Entry(participant).State = EntityState.Modified;
           _db.SaveChanges();
           return RedirectToAction("Index", new { id = viewModel.Id });
      }
      return View(viewModel);
}
Mustapha Larhrouch
  • 3,373
  • 3
  • 14
  • 28
  • Thanks this fixed that error, however it raised another - I try to update the participant.Country = viewModel.CountryId and am told "can't implicitly convert type int to type to Project.Model.Country". – jonnow May 12 '17 at 09:23
  • 1
    try Project.Model.Country = new Country (){CountryId = viewModel.CountryId } – Mustapha Larhrouch May 12 '17 at 09:24
  • 1
    Thank you, building on that I grabbed a single item from the DB and applied it like so var country = _db.Countrys.Single(g => g.Id == viewModel.CountryId); participant.Country = country; – jonnow May 12 '17 at 09:42