In a C# MVC WebApp, I have a CallDetailViewModel
that contains a list of CallerViewModels
and it has a List of PhoneNumberViewModels
. I'm trying to link them all together properly.
Not shown here, but I am also trying to both load existing values and add new/remove values, so I don't know what's being sent to the controller ahead of time.
I've tried following this 2012 guide that has a very similar problem I found online, but no luck yet: Code Project Article
I also tried moving the List of PhoneNumberViewModels
to the CallDetailViewModel
, and while I was able to pass the phone numbers to my controller I didn't have a clear way to link them to the appropriate CallerViewModel
.
I want to be able to add and remove PhoneNumbers
from Callers
and Callers
from the CallDetail
.
I've removed my buttons and AJAX regarding those for now, as it's not my main problem.
Here are my simplified ViewModels and Views:
ViewModels
CallDetailViewModel.cs
namespace PROJECT_NAME.ViewModels
{
public class CallDetailsViewModel
{
public Guid Id { get; set; }
public string EnteredByEmail { get; set; }
public List<CallerViewModel> CallerViewModels { get; set; }
}
}
CallerViewModel.cs
namespace PROJECT_NAME.ViewModels
{
public class CallerViewModel
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public List<PhoneNumberViewModel> PhoneNumberViewModels { get; set; }
}
}
PhoneNumberViewModel.cs
namespace PROJECT_NAME.ViewModels
{
public class PhoneNumberViewModel
{
public Guid Id { get; set; }
public string Number { get; set; }
}
}
Views
CallDetail.cshtml
@using PROJECT_NAME.ViewModels
@model CallDetailsViewModel
<div class="container">
@using (Html.BeginForm("SubmitCallDetails", "Home", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(m => m.Id)
<div class="well">
@* Call Details *@
<div class="row">
<fieldset">
<legend>Call Details</legend>
</fieldset>
<div class="form-group">
@Html.LabelFor(m => m.EnteredByEmail, new {@class = "control-label"})
@Html.TextBoxFor(m => m.EnteredByEmail, new {@class = "form-control"})
</div>
</div>
@* Caller Details *@
<div class="row">
<fieldset>
<legend>Callers</legend>
</fieldset>
</div>
@* Render each existing caller. Each caller gets it's own well to create a visual seperation between them. *@
@if (Model.CallerViewModels.Count == 0)
{
<div class="well">
@{ Html.RenderPartial("_PartialCallerInfo", new CallerViewModel());}
</div>
}
@foreach (var callerViewModel in Model.CallerViewModels)
{
<div class="well">
@{ Html.RenderPartial("_PartialCallerInfo", callerViewModel); }
</div>
}
</div>
<div class="row">
<div class="form-group">
<button class="btn btn-danger" type="reset">Reset</button>
</div>
<div class="form-group">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</div>
}
</div>
_PartialCallerInfo.cshtml
@using PROJECT_NAME.ViewModels
@model CallerViewModel
@using (Html.BeginCollectionItem("CallerViewModels"))
{
<div class="row">
@Html.HiddenFor(m => m.Id)
<div class="form-group">
@Html.LabelFor(m => m.FirstName, new { @class = "control-label" })
@Html.TextBoxFor(m => m.FirstName, new { @class = "form-control"})
</div>
</div>
@if (Model.PhoneNumberViewModels.Count == 0)
{
@{ Html.RenderPartial("_PartialCallerPhoneNumber", new PhoneNumberViewModel());}
}
@foreach (var phoneNumberViewModel in Model.PhoneNumberViewModels)
{
@{ Html.RenderPartial("_PartialCallerPhoneNumber", phoneNumberViewModel); }
}
}
_PartialCallerPhoneNumber.cshtml
@using PROJECT_NAME.ViewModels
@model PhoneNumberViewModel
@using (Html.BeginCollectionItem("PhoneNumberViewModels"))
{
<div class="row">
@Html.HiddenFor(m => m.Id)
<div class="form-group">
@Html.LabelFor(m => m.Number, new { @class = "control-label" })
@Html.TextBoxFor(m => m.Number, new { @class = "form-control"})
</div>
</div>
}
See Question&Answers more detail:
os