New to MVC.NET (and C# generally...and developing generally) and trying to my head around ViewModels. I've got a pretty basic requirement. I have Actor, UseCase and Project entities. To create a new UseCase I want a view with a DropDownListFor the Actors that are in the same Project as the UseCase. The project id is in the URL. I've been following this How to bind a selectlist with viewmodel? but I'm getting stuck with an error:
DataBinding: 'System.Web.Mvc.SelectListItem' does not contain a property with the name 'ActorId'.
Also, I don't really know exactly how to do the mapping in my POST method - I'm happy to do this manually for now without AutoMapper.
ViewModel:
public class UserGoalsStepViewModel
{
public enum GoalLevel
{
Summary, UserGoal, SubGoal,
}
public int ProjectId { get; set; }
public int ActorId { get; set; }
public SelectList ActorList { get; set; }
public string Title { get; set; }
public GoalLevel Level { get; set; }
public UserGoalsStepViewModel ()
{
}
}
UPDATED: Controller: Has been updated to reflect changes discussed in comments below.
What's happening:
1. Model is correctly populated when the view is created in the GET (values for ProjectId, Level and ActorList are right, actorId is '0' and Title is null. All as expected.
2. On the POST though, Title gets set to "5" (which is the actually the Id of the selected actor, ActorId = 0 still, Level gets the correct value and ProjectId loses its value. So, obviously I need to do something with the SelectList definition but I'm not sure why the ProjectId is getting lost?
// GET: UseCases/Create
public ActionResult Create(int id)
{
ViewBag.projectId = id;
//Populate the ViewModel
UserGoalsStepViewModel model = new UserGoalsStepViewModel()
{
ProjectId = id,
ActorList = new SelectList(db.Actors.Where(a => a.projectID == id), "id", "Title"),
};
return View(model);
}
// POST: UseCases/Create
// 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 ActionResult Create([Bind(Include = "ProjectId,ActorId,Title,Level")] UserGoalsStepViewModel model, int id)
{
ViewData["Actors"] = new SelectList(db.Actors.Where(a => a.projectID == id), "id", "Title");
if (ModelState.IsValid)
{
//Create a use case object to map to, which can then be saved in the DB
UseCase uc = new UseCase();
uc.ProjectID = model.ProjectId;
uc.ActorID = model.ActorId;
uc.Level = (Level)model.Level;
db.SaveChanges();
return RedirectToAction("Index", new { id = model.ProjectId });
}
return View(model);
}
View:
@Html.DropDownListFor(model => model.Title, new SelectList(Model.ActorList, "ActorId", "Title"), new { @class = "form-control" })