Home > Blockchain >  Am I using KubernetesClient correctly with Blazor to list objects asynchronously?
Am I using KubernetesClient correctly with Blazor to list objects asynchronously?

Time:03-25

TL/DR:

  1. I don't know if I'm using the asynchronous programming features of C# and Blazor correctly.
  2. Even though things technically work, I'd like some guidance if I'm doing things correctly.
  3. Also, I'm having issues trying to get my "loading spinner" to work. What am I doing wrong?

I'd like some guidance of my code is doing things the correct way.

I'm currently trying to use KubernetesClient with a Blazor webapp to interact with my kubernetes cluster.

As a test, I've tried to list nodes in a cluster, asynchronously. Things appear to work, but I'm unsure if I'm doing this correctly. Please see the code below:

@page "/kclient"
@using k8s

<PageTitle>Kubernetes Client Test</PageTitle>

<h1>Kubernetes Client Test</h1>
<br />
<button  @onclick="@GetNodesAsync">Refresh Node List</button>
<br /><br />
<p>LOADING = @spin.ToString()</p>
<label>Node list:</label>
@if (spin)
{
    <div ></div>
}else
{
    <ul>
        @if (MyNodes == null || MyNodes.Count == 0)
        {
            <li>No Nodes. Please try to refresh the node list.</li>
        }else
        {
            @foreach(string node in MyNodes)
            {
                <li>@node</li>
            }
        }

    </ul>
}

@code {
    public bool spin = false;
    public IKubernetes client { get; set; }
    public List<string> MyNodes { get; set; }

    protected override void OnInitialized()
    {
        spin = false;
        KubernetesClientConfiguration config = KubernetesClientConfiguration.BuildConfigFromConfigFile("C:\\Users\\DevAdmin\\.kube\\config");
        client = new Kubernetes(config);
        System.Console.WriteLine("Base URI: "   client.BaseUri);
    }

    async Task GetNodesAsync()
    {
        spin = true;
        Task.Delay(1500).Wait();
        await InvokeAsync(GetNodes);   
        spin = false;
        await Task.CompletedTask;
    }

    public async void GetNodes()
    {
        MyNodes = null;
        MyNodes = new List<string>();
        System.Console.WriteLine("=== TRYING TO GET ALL NODES! ===");
        var nodeList = await client.ListNodeAsync();
        if (nodeList.Items.Count == 0)
        {
            Console.WriteLine("Empty! There are no nodes!");
        }
        else
        {
            foreach (var item in nodeList.Items)
            {
                //Console.WriteLine(item.Metadata.Name);
                MyNodes.Add(item.Metadata.Name);
            }
        }
        StateHasChanged();
    }
}

The code above produces the page below: enter image description here

When you click on the button "Refresh Node List" button, it will use the KubernetesClient library to get a list of Kubernetes nodes. Because I'm still new to .NET, Blazor, and asynchronous programming, I'm unsure if the way I'm retrieving the list of nodes and then showing it in a Blazor (razor?) page is correct.

Also I've been trying to show a loading spinner while waiting for the client to retrieve data, but I've been unable to get that working, and I'm sure it's because I'm not using async/tasks correctly.

Any guidance on my usage of the asynchronously programming features of C#/.NET or anything else with the code I've provided would be greatly appreciated.

Thanks in advance.

CodePudding user response:

I can spot a few issues. Always avoid async void.

async Task GetNodesAsync()
{
    spin = true;
    //Task.Delay(1500).Wait();      -- .Wait() blocks the UI
    await Task.Delay(1500);
    //await InvokeAsync(GetNodes);  -- this won't run on another Thread
    await GetNodes();   
    spin = false;
    //await Task.CompletedTask;
}

//public async void GetNodes()
public async Task GetNodes()
{
    ... // as before
    //StateHasChanged();  -- not needed
}
  • Related