Display list of countries - Code

Client Project

Pages > CountryListPage.razor

@page "/countrylist"

@inject ICountryService CountryService;

<PageTitle>Countries List</PageTitle>

<h3>Countries List</h3>

<table class="table">
    <thead>
        <tr>
            <th>Country ID</th>
            <th>Country Name</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var country in CountryService.Countries)
        {
            <tr>
                <td>@country.CountryId</td>
                <td>@country.CountryName</td>
            </tr>
        }

    </tbody>
</table>

@code {
    protected override async Task OnInitializedAsync()
    {
        await CountryService.GetCountries();
    }

}

Services > CountryService > CountryService.cs

using System.Net.Http.Json;

namespace BlazorCountriesWasm.Client.Services.CountryService
{
    public class CountryService : ICountryService
    {
        private readonly HttpClient _http;
        public CountryService(HttpClient http)
        {
            _http = http;
        }

        public List<Country> Countries { get; set; } = new List<Country>();
        public HttpClient? Http { get; }        //? here gets rid of green squiggly on "Public CountryService(HttpClient http)"

        public async Task GetCountries()
        {
            var result = await _http.GetFromJsonAsync<List<Country>>("api/country");
            if (result != null)
                Countries = result;
        }
        public Task<Country> GetCountryById(int id)
        {
            throw new NotImplementedException();
        }
    }
}

Services > CountryService > ICountryService.cs

namespace BlazorCountriesWasm.Client.Services.CountryService
{
    public interface ICountryService
    {
        List<Country> Countries { get; set; }

        Task GetCountries();
        Task<Country> GetCountryById(int id);
    }
}

Shared > NavMenu.razor

<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="">Countries & Cities</a>
        <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
            <span class="navbar-toggler-icon"></span>
        </button>
    </div>
</div>

<div class="@NavMenuCssClass nav-scrollable" @onclick="ToggleNavMenu">
    <nav class="flex-column">
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="counter">
                <span class="oi oi-plus" aria-hidden="true"></span> Counter
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="fetchdata">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
            </NavLink>
        </div>
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="countrylist">
                <span class="oi oi-list" aria-hidden="true"></span> Country List
            </NavLink>
        </div>
    </nav>
</div>

@code {
    private bool collapseNavMenu = true;

    private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;

    private void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }
}

_Imports.razor

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using BlazorCountriesWasm.Client
@using BlazorCountriesWasm.Client.Shared
@using BlazorCountriesWasm.Client.Services.CountryService

Programs.cs

global using BlazorCountriesWasm.Client.Services.CountryService;
global using BlazorCountriesWasm.Shared;
using BlazorCountriesWasm.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<ICountryService, CountryService>();

await builder.Build().RunAsync();

Server Project

Controllers > CityController.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace BlazorCountriesWasm.Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CityController : ControllerBase
    {
        public static List<City> cities = new List<City>
        {
            new City
            {
                CityId = 1,
                CityName = "London",
                CityPopulation = 9000000,
                CountryId = 1
            },
            new City
            {
                CityId = 2,
                CityName = "Birmingham",
                CityPopulation = 1500000,
                CountryId = 1
            },
            new City
            {
                CityId = 3,
                CityName = "Oxford",
                CityPopulation = 250000,
                CountryId = 1
            },
            new City
            {
                CityId = 4,
                CityName = "Cambridge",
                CityPopulation = 200000,
                CountryId = 1
            },
            new City
            {
                CityId = 5,
                CityName = "Paris",
                CityPopulation = 7500000,
                CountryId = 2
            },
            new City
            {
                CityId = 6,
                CityName = "Toulouse",
                CityPopulation = 200000,
                CountryId = 2
            },
            new City
            {
                CityId = 7,
                CityName = "Grenoble",
                CityPopulation = 200000,
                CountryId = 2
            }
        };

        [HttpGet]
        public async Task<ActionResult<List<City>>> GetCities()
        {
            return Ok(cities);
        }

        [HttpGet]
        [Route("{CityId}")]
        //Or you can combine the two lines as: [HttpGet("{CityId}")]
        public async Task<ActionResult<City>> GetSingleCity(int CityId)
        {
            var city = cities.FirstOrDefault(c => c.CityId == CityId);
            if (city == null)
            {
                return NotFound();
            }
            else
            {
                return Ok(city);
            }
        }
    }
}

Controllers > CountryController.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace BlazorCountriesWasm.Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CountryController : ControllerBase
    {
        public static List<Country> countries = new List<Country>
        {
            new Country {CountryId = 1, CountryName = "United Kingdom"},
            new Country {CountryId = 2, CountryName ="France"}
        };

        [HttpGet]
        public async Task<ActionResult<List<Country>>> GetCountries()
        {
            return Ok(countries);
        }

        [HttpGet]
        [Route("{CountryId}")]
        //Or you can combine the two lines as: [HttpGet("{CountryId}")]
        public async Task<ActionResult<Country>> GetSingleCountry(int CountryId)
        {
            var country = countries.FirstOrDefault(c => c.CountryId == CountryId);
            if (country == null)
            {
                return NotFound("Sorry, no country found.");
            }
            else
            {
                return Ok(country);
            }
        }

    }
}

Shared Project

City.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BlazorCountriesWasm.Shared
{
    public class City
    {
        public int CityId { get; set; }
        public string CityName { get; set; } = string.Empty;
        public int CityPopulation { get; set; } = 0;
        public int CountryId { get; set; }
    }
}

Country.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BlazorCountriesWasm.Shared
{
    public class Country
    {
        public int CountryId { get; set; }
        public string CountryName { get; set; } = String.Empty;
    }
}