Reputation: 193
I'm following along in the book C# 8.0and .NET Core 3.0 - Modern Cross-Platform Development
I'm currently in Chapter 15 on exercise 15.2 where we are tasked with creating a Razor Page that produces a list of customers grouped by country. When you click on a customer name, it takes you to a new page showing the full contact details of that customer and a list of their orders.
Taking baby steps, I have built a page that has a card that will have the header as the country and then list each customer name on the card. However, my foreach loop is spitting out each data column under Customer.Country. So if there are 11 countries with Germany, it makes 11 cards with Germany as the title (see image).
It is also populating all of the customer's names as well under each country.
I found that I can use GroupBy() but as I explain below, that causes an invalid cast exception.
customers.cshtml
@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using NorthwindEntitiesLib
@model NorthwindWeb.Pages.CustomersModel
<div class="row">
<h1 class="display2">Customers</h1>
</div>
<div class="row">
@foreach (Customer customer in Model.Customers)
{
<div class="card border-info mb-3" style="max-width: 18rem">
<div class="card-header text-white bg-info">
@customer.Country
</div>
<ul class="list-group list-group-flush">
@foreach (var name in Model.Customers)
{
<li class="list-group-item">@name.ContactName</li>
}
</ul>
</div>
}
</div>
customers.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using NorthwindContextLib;
using NorthwindEntitiesLib;
namespace NorthwindWeb.Pages
{
public class CustomersModel : PageModel
{
private Northwind db;
public CustomersModel(Northwind injectedContext)
{
db = injectedContext;
}
public IEnumerable<Customer> Customers { get; set; }
public void OnGet()
{
Customers = db.Customers
.ToArray();
}
}
}
NorthwindEntitesLib
namespace NorthwindEntitiesLib
{
public class Customer
{
public string CustomerID { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string ContactTitle { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public ICollection<Order> Orders { get; set; }
}
}
I have tried using GroupBy to group the Countries and then populate the list but it gives an error for an invalid casting of type string.
@foreach (Customer customer in Model.Customers.GroupBy(c =>c.Country))
{
<div class="card border-info mb-3" style="max-width: 18rem">
<div class="card-header text-white bg-info">
@customer.Country
</div>
<ul class="list-group list-group-flush">
@foreach (var name in Model.Customers)
{
<li class="list-group-item">@name.ContactName</li>
}
</ul>
</div>
}
InvalidCastException: Unable to cast object of type 'System.Linq.Grouping`2[System.String,NorthwindEntitiesLib.Customer]' to type 'NorthwindEntitiesLib.Customer'.
Upvotes: 3
Views: 3427
Reputation: 2281
Ok, so GroupBy
gives you a Key
property. That is what you will use for the country name.
So basically, you will use the following (warning untested)
@foreach (var country in Model.Customers.GroupBy(c =>c.Country))
{
<div class="card border-info mb-3" style="max-width: 18rem">
<div class="card-header text-white bg-info">
@country.Key
</div>
<ul class="list-group list-group-flush">
@foreach (var customer in country.ToArray())
{
<li class="list-group-item">@customer.ContactName</li>
}
</ul>
</div>
}
Upvotes: 3
Reputation: 75
GroupBy is the command of System.Linq. You can't simply use it in random places without mentioning System.Linq.
Upvotes: -2