I am an MVC noob, but trying to implement best practices and keeping as little code in a view as possible. The issue I'm running into is that I have a list of members and their associated statuses. I can pass this information to the view and render each member and their status in one line, but I want the view to group the data and look like the following:
Status: Active
- John Doe
- Mary Jane
- etc...
Status: Inactive
- Mark Smith
- etc...
I don't think it's best practice to have some sort of multi-level for loop in a view (correct me if I'm wrong), and that I should have some sort of partial view for the member information (right now, just FirstName and LastName, but will eventually be more complex) and then some sort of main view for the grouping by status that then renders the partial view for each member. I am also trying to use the ViewModel approach to keep clean views. Any suggestions for how to do this according to best practices are appreciated! Also, any comments on my current code (organization, cleanliness, etc.) are welcome.
--- If you want to see my current code, it is as follows ---
Here's the Controller that sends the results of the query to the view:
namespace MyApp.Web.Controllers
{
public class MemberController : Controller
{
private IMemberQueries _memberQuery;
public MemberController(IMemberQueries memberMemberQuery)
{
_memberQuery = memberMemberQuery;
}
public ViewResult Index()
{
return View(_memberQuery.GetMembersWithStatus());
}
}
}
Here's the Query code:
namespace MyApp.Web.ViewModels
{
public class MemberQueries : IMemberQueries
{
private IMemberRepository _memberRepository;
public MemberQueries(IMemberRepository memberMemberRepository)
{
_memberRepository = memberMemberRepository;
}
public IEnumerable<MembersIndexViewModel> GetMembersWithStatus()
{
return
_memberRepository.Member.Include(m => m.Status).Select(
m => new MembersIndexViewModel { FirstName = m.FirstName, LastName = m.LastName, Status = m.Status.StatusName });
}
}
}
Here's my ViewModel to limit the data going to the view:
namespace MyApp.Web.ViewModels
{
public class MembersIndexViewModel
{
public string LastName { get; set; }
public string FirstName { get; set; }
public string Status { get; set; }
}
}
Here's the view and how it uses the viewmodel to display each member's name and status, but it's not grouped:
@model IEnumerable<MyApp.Web.ViewModels.MembersIndexViewModel>
<h2>Member List</h2>
@foreach (var member in Model)
{
<div>
<h3>@member.LastName, @member.FirstName - @member.Status</h3>
</div>
}
UPDATE: Here's what I had to change for it to work based on Romias's assistance
Update the MemberQueries to call ToList() to cause immediate calling of the query:
public IEnumerable<MembersIndexViewModel> GetMembersWithStatus()
{
return
_memberRepository.Member.Include(m => m.Status).Select(
m => new MembersIndexViewModel { FirstName = m.FirstName, LastName = m.LastName, Status = m.Status.StatusName }).ToList();
}
Here's the updated view that now works:
<h2>Member List</h2>
@foreach (string status in Model.Select(x => x.Status).Distinct())
{
<h2>@status:</h2>
string memberStatus = status;
foreach (MembersViewModel member in Model.Where(m => m.Status == memberStatus))
{
<div>@member.LastName, @member.FirstName</div>
}
}