Search code examples
c#.netforeachblazor

How to get a list of another list from different API routes in Blazor?


I've hit a brickwall and I'm wondering how to solve this problem. I'm trying to learn Blazor and I'm using an open API to receive data about Game of Thrones Houses and all their sworn members. So what I'm basically trying to receive is a list inside another list but with two different routes. My expected output is to be clicking a house name and another list should be added to my table with the members.

Expected output

House Targaryen - Daenerys Targaryen
                - Aegon Targaryen

etc...

House route https://anapioficeandfire.com/api/houses/378 Character route https://anapioficeandfire.com/api/characters/33

    @page "/fetchdata"
@using System.Text.Json.Serialization
@using System.Text.Json
@inject HttpClient Http


<h1>Game of Thrones</h1>

<p>This component demonstrates fetching data from the server.</p>

@if (houses == null)
{
    <p>
        <em>Loading...</em>
    </p>
}
else
{
    <table class="table">
        <thead>
        <tr>
            <th>Houses</th>
        </tr>
        </thead>
        <tbody>
        @foreach (var house in houses.Take(5))
        {
            <tr>
                <td>@house.Name</td>
                @foreach (var character in house.SwornMembers.Take(5))
                {
                    <td>
                        <tr>@character</tr>
                    </td>
                }
            </tr>
        }
        </tbody>

    </table>
}

@code {
    List<House> houses;
    List<Character> characters;

    protected override async Task OnInitializedAsync()
    {
        houses = await Http.GetFromJsonAsync<List<House>>("https://anapioficeandfire.com/api/houses/");

        Console.WriteLine(houses);
    }

    public class House
    {
        public string Name { get; set; }
        public List<Character> SwornMembers { get; set; }
    }

    public class Character
    {
        public string Name { get; set; }
        public string Gender { get; set; }
        public string Culture { get; set; }
        public string Born { get; set; }
    }

}

Solution

  • From taking a quick glance at the api you can't load multiple characters via something like ?id=1,2,3,4.

    Like timur said, you'll have to make a bunch of GetFromJSONAsync calls. If you look at the json response, the SwornMembers property isn't an object, but a URL you'll have to load separately. In your House class, change List<Character> to List<string>

    Then create a CharacterFromApi component that takes the url. <CharacterFromApi URL="@character"/>

    @foreach (var character in house.SwornMembers.Take(5))
    {
        <td>
            <tr><CharacterFromApi URL="@character"/></tr>
        </td>
    }
    
    //FYI the usings can be moved into the _Imports.razor file
    @using System.Text.Json.Serialization
    @using System.Text.Json
    @inject HttpClient Http
    
    <div>
       @(Character?.Name)
    </div>
    
    @code {
        [Parameter] 
        public string URL { get; set; }   
    
        Character Character { get; set; }
    
        protected override async Task OnInitializedAsync()
        {
            Character = await Http.GetFromJsonAsync<Character>(URL);
        }
    
        public class Character
        {
            public string Name { get; set; }
            public string Gender { get; set; }
            public string Culture { get; set; }
            public string Born { get; set; }
        }
    }