It's time to ask the internet. I'm a student and really new to MVC + coding in general, but I can't for the life of me figure out why this isn't working. Probably something really obvious. :/
I have a View (AddMemberToGroup) that is strongly-typed to a viewmodel (PersonGroupingViewModel). What am I trying to do is add a Person to a Group, with the user selecting a group from a dropdown list in the View.
Viewmodel:
public class PersonGroupingViewModel
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set;}
public List<Group> Memberships { get; set; }
public SelectList AllGroups { get; set; }
public int SelectedGroupId { get; set; }
}
Controller:
//GET People/AddToGroup
public ActionResult AddMemberToGroup(int? PersonId)
{
if (PersonId == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Person person = db.People.Find(PersonId);
if (person == null)
{
return HttpNotFound();
}
SelectList allthegroups = new SelectList(db.Groups, "GroupId", "Name");
PersonGroupingViewModel viewmodel = new PersonGroupingViewModel();
viewmodel.PersonId = person.PersonId;
viewmodel.FirstName = person.FirstName;
viewmodel.LastName = person.LastName;
viewmodel.AllGroups = allthegroups;
//viewmodel.Memberships cannot be empty
if (person.Memberships == null)
{
viewmodel.Memberships = new List<Group>();
}
else
{
viewmodel.Memberships = person.Memberships.ToList();
}
return View(viewmodel);
}
//POST: People/AddToGroup
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddMemberToGroup(PersonGroupingViewModel vm)
{
SelectList allthegroups = new SelectList(db.Groups, "GroupId", "Name");
vm.AllGroups = allthegroups;
int PersonId = vm.PersonId;
int GroupId = vm.SelectedGroupId;
Person person = db.People.Find(PersonId);
Group group = db.Groups.Find(GroupId);
group.Members.Add(person);
db.SaveChanges();
return View(vm);
}
View form (strongly-typed to PersonGroupingViewModel):
Add Member To Group
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div>
<h4>Groups @Html.DisplayFor(model => model.FirstName) is already in:</h4>
<ul>
@foreach (var group in Model.Memberships)
{
<li>@Html.DisplayFor(modelItem => group.Name)</li>
}
</ul>
</div>
<div class="form-horizontal">
<h4>Add @Html.DisplayFor(model => model.FirstName) @Html.DisplayFor(model => model.LastName) To Group:</h4>
@Html.HiddenFor(model => model.PersonId)
<div class="form-group">
<label>Group: </label>
@Html.DropDownListFor(m => m.SelectedGroupId, Model.AllGroups, String.Empty)
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Add To Group" class="btn btn-default" />
</div>
</div>
</div>
}
When I click 'submit' in the browser I get back a URL:
localhost:54696/People/AddMemberToGroup?PersonId=1
Along with exception "Object reference not set to an instance of an object" on the line Group group = db.Groups.Find(GroupId); in the controller.
Is the viewmodel coming back empty or not at all? I am not sure what is going on and would appreciate someone attempting explaining it in small words. I've done a lot of Googling and tried several suggestions from that but in the end I feel as though I'm going in circles.
AddMemberToGroup(int? ID)assuming your using the default routes or add a specific routeurl: yourController/AddMemberToGroup/{PersonId}- user3559349nulllabel option for the select and not checkingModelStateso if no group is selected your will likely throw an exception. You need to debug you code and check that all values are correctly set and notnull. However I suggest that this is a poor user interface. You can select only one group at a time, and you can also select groups that have already been selected (also possibly throwing an exception) and your not reassigning the value ofvm.Membershipsbefore you return the view so@foreach (var group in Model.Memberships)will also throw an exception. - user3559349