Home > Net >  MVC Core How to correctly Edit Existing model using viewmodel
MVC Core How to correctly Edit Existing model using viewmodel

Time:12-10

I am trying to Edit existing instance of class project using a viewmodel. I think I have no issues in the GET method of the Edit (everything renders fine on the View) but I am struggling with the POST method. The problem is the POST method creates new instance of the project instead updating the current one.

This is my model:

    public class Project
    {
        public int ProjectId { get; set; }
        public string Name { get; set; }
        public string Budget { get; set; }
        public string BusinessCase { get; set; }
        public string StartDate { get; set; }
        public string FinishDate { get; set; }

        public int ClientId { get; set; }
        public Client Client { get; set; }
        public ICollection<ProjectMember> ProjectMembers { get; set; }

        public Project()
        {
        }
    }
}

This is my CreateProjectViewModel (some of the attributes are not used in the controller code below):

 public class CreateProjectViewModel
    {
//project
        public int ProjectId { get; set; }
        public string Name { get; set; }
        public string Budget { get; set; }
        public string BusinessCase { get; set; }
        public string StartDate { get; set; }
        public string FinishDate { get; set; }

//clients
        public int ClientId { get; set; }
        public Client Client { get; set; }
        public ICollection<ProjectMember> ProjectMembers { get; set; }

        //Members
        public int MemberId { get; set; }
        public Member Member { get; set; }
        public Project Project { get; set; }
        public List<SelectListItem> Members { get; set; }

        public IEnumerable<SelectListItem> Clients { get; set; }
        public IEnumerable<int> SelectedMembers { get; set; }

        public CreateProjectViewModel() { }
    }
}

This is My Edit GET method in ProjectController:

public async Task<IActionResult> Edit(int? id)
    {

    Project project = await _context.Project
    .FirstOrDefaultAsync(m => m.ProjectId == id);

    var members = _context.Member
                .Select(m => new SelectListItem { Value = m.MemberId.ToString(), Text = m.MemberName }).ToList();
    var clients = _context.Client
  .Select(r => new SelectListItem { Value = r.ClientId.ToString(), Text = r.Name }).ToList();


    CreateProjectViewModel viewmodel = new CreateProjectViewModel
    {
        Name = project.Name,
        Budget = project.Budget,
        BusinessCase = project.BusinessCase,
        StartDate = project.StartDate,
        FinishDate = project.FinishDate,
        Project = project,
        Clients = clients,
        Members = members



    };
    return View(viewmodel);

This is my Edit POST method in ProjectController which is wrongly creating a new project instead of updating the current project: (The controller is trying to save values to Project Model and at the same time in Join table containing MemberId and ProjectID - this works fine when creating a project, not sure if correct for updating)

public IActionResult Edit(int? id, CreateProjectViewModel model)
        {
            Project project = _context.Project
            .Single(m => m.ProjectId == id);


//this is to post in many-to-many join table between Member and Project
            var projectID = project.ProjectId;
            var memberID = model.MemberId;
            IList<ProjectMember> existingItems = _context.ProjectMembers
                .Where(cm => cm.MemberId == memberID)
                .Where(cm => cm.ProjectId == projectID).ToList();

            if (existingItems.Count == 0)
            {

                foreach (var selectedId in model.SelectedMembers)
                {
                    _context.ProjectMembers.Add(new ProjectMember
                    {
                        ProjectId = project.ProjectId,
                        MemberId = selectedId,
                    });
                }
            }

//this is to update the values in the project which refers to ProjectID
            project.ProjectId = model.ProjectId;
            project.Name = model.Name;
            project.Budget = model.Budget;
            project.BusinessCase = model.BusinessCase;
            project.StartDate = model.StartDate;
            project.FinishDate = model.FinishDate;
            project.ClientId = model.ClientId;

            _context.Entry(project).State = EntityState.Modified;
            _context.SaveChanges();
            return RedirectToAction("Index");
        }

Can you guys advise me what should be changed in either method to get the expected result?

Thanks a lot.

CodePudding user response:

After some digging done this is the working code.

Edit POST Method:

 public IActionResult Edit(int? id, CreateProjectViewModel viewmodel)
        {
            if (ModelState.IsValid)
            { 
                var project = _context.Project
            .SingleOrDefault(m => m.ProjectId == id);

  //this is to update the Project from the viewmodel
                project.Name = viewmodel.Name;
            project.Budget = viewmodel.Budget;
            project.BusinessCase = viewmodel.BusinessCase;
            project.StartDate = viewmodel.StartDate;
            project.FinishDate = viewmodel.FinishDate;
            project.ClientId = viewmodel.ClientId;

//code below is to validate if the matched primary keys of Project and Member are not already in ProjectMembers table
  foreach (var selectedId in viewmodel.SelectedMembers)
            { 
                var projectID = project.ProjectId;
                var memberID = selectedId;
 
                
            IList<ProjectMember> existingItems = _context.ProjectMembers
                .Where(cm => cm.MemberId == memberID)
                .Where(cm => cm.ProjectId == projectID).ToList();

                    if (existingItems.Count == 0)
            {
                 //this is to add new entry into ProjectMembers table   
                    _context.ProjectMembers.Add(new ProjectMember
                    {
                        ProjectId = project.ProjectId,
                        MemberId = selectedId,
                    });
                } 
            }
            _context.SaveChanges();
            }
            return RedirectToAction("Index");
  • Related