Cancel Background long-running Tasks when a user navigates to another page in Blazor

@page "/State"
@implements IDisposable

<h3>State</h3>

<p>@output</p>

@code {
    private string output = "";
    private CancellationTokenSource cts = new();
    
    protected override async Task OnInitializedAsync()
    {
        while (!cts.IsCancellationRequested)
        {
            await Task.Delay(1000);
            var rnd = new Random();
            output = rnd.Next(1, 50).ToString();
            StateHasChanged();
        }
        
        // cts.Token.ThrowIfCancellationRequested();
    }
    
    public void Dispose()
    {
        cts.Cancel();
        cts.Dispose();
    }
}

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-6.0#cancelable-background-work
https://www.syncfusion.com/faq/blazor/web-api/how-do-i-cancel-background-long-running-tasks-when-a-user-navigates-to-another-page-in-blazor

Refresh a Blazor Component with StateHasChanged

@page "/State"
<h3>State</h3>

<p>@output</p>

@code {
    private string output = "";
    
    protected override async Task OnInitializedAsync()
    {
        while (true)
        {
            await Task.Delay(1000);
            var rnd = new Random();
            output = rnd.Next(1, 50).ToString();
            StateHasChanged();
        }
    }
}

References
https://www.techiediaries.com/refresh-blazor-component-statehaschanged-invokeasync/
https://docs.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-6.0#state-changes-statehaschanged

Optimizing Blazor performance using the @key directive

The @key directive is important when creating components dynamically by iterating list/IEnumerable. Adding the @key will ensure proper change detection and UI update in the collection of components.

<ul class="mt-5">
    @foreach (var person in People)
    {
        <li @key="person.Id">@person.Id, @person.Name</li>
    }
</ul>

Tip: Always use @key for components that are generated in a loop at runtime.

References
https://blazor-university.com/components/render-trees/optimising-using-key/
https://www.meziantou.net/optimizing-blazor-performance-using-the-key-directive.htm
https://www.syncfusion.com/faq/blazor/components/what-is-the-use-of-key-property

Get the Reference or Instance of a Component in ASP.NET Core Blazor

o capture a component reference in Blazor, use the @ref directive attribute. The value of the attribute should match the name of a settable field with the same type as the referenced component.

<MyLoginDialog @ref="loginDialog" ... />

@code {
    MyLoginDialog loginDialog;

    void OnSomething()
    {
        loginDialog.Show();
    }
}

References
https://docs.microsoft.com/en-us/dotnet/architecture/blazor-for-web-forms-developers/components#capture-component-references
https://www.syncfusion.com/faq/blazor/components/how-do-i-get-the-reference-or-instance-of-a-component

Two-way Binding in Blazor Component

We need to tell Blazor that the consuming page wants to use two-way binding.To use two-way binding on a parameter simply prefix the HTML attribute with the text @bind-. This tells Blazor it should not only push changes to the component, but should also observe the component for any changes and update its own state accordingly.

Two-way binding in Blazor uses a naming convention. If we want to bind to a property named SomeProperty, then we need an event call-back named SomeProperyChanged. This call-back must be invoked any time the component updates SomeProperty.

SecondComponent.razor

<h3>SecondComponent</h3>

<button @onclick="Callback">Increment</button>

@code {

    [Parameter]
    public int CounterValue { get; set; }

    [Parameter]
    public EventCallback<int> CounterValueChanged { get; set; }

    private async Task Callback()
    {
        if (CounterValue >= 20)
        {
    // reset counter
            CounterValue = 0;
        }
        else
        {
            CounterValue++;
        }

    // fire event
        await CounterValueChanged.InvokeAsync(CounterValue);
    }

}

Counter.razor

@page "/counter"

<SecondComponent @bind-CounterValue="counter"></SecondComponent>

<p>@counter</p>

@code
{
    private int counter = 2;
}

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-6.0#binding-with-component-parameters
https://blazor-university.com/components/two-way-binding/
https://stackoverflow.com/questions/57932850/how-to-make-two-way-binding-on-blazor-component

Communicate Between Components in Blazor using Events

TestComponent.razor

<h3>TestComponent</h3>

<p><button @onclick="Button1_Clicked">Button1</button></p>
<p><button @onclick="Button2_Clicked">Button2</button></p>

@code {
    
    [Parameter]
    public EventCallback Event1 { get; set; }
    
    [Parameter]
    public EventCallback<TestModel> Event2 { get; set; }

    private void Button1_Clicked(MouseEventArgs obj)
    {
        Event1.InvokeAsync("Event1 is fired");
    }

    private void Button2_Clicked(MouseEventArgs obj)
    {
        Event2.InvokeAsync(new TestModel() {Message = "Event2 is fired", Date = DateTime.Now});
    }
}

TestModel.cs

namespace BlazorApp1;

public class TestModel
{
    public DateTime Date { get; set; }
    
    public string Message { get; set; }
}

Index.razor

@page "/"

<TestComponent Event1="Callback" Event2="Callback2"></TestComponent>

<div>@((MarkupString) output)</div>

@code {
    private string output = "";

    private void Callback2(TestModel obj)
    {
        output += "<p>" + obj.Message + ", ";
        output += obj.Date +"</p>";
    }

    private void Callback(object obj)
    {
        output += "<p>"+obj+"</p>";
    }
}

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-6.0#eventcallback
https://blazor-university.com/components/component-events/
https://chrissainty.com/3-ways-to-communicate-between-components-in-blazor/

Trust the ASP.NET Core HTTPS development certificate on Ubuntu

Ubuntu trust the certificate for service-to-service communication

dotnet dev-certs https
sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
sudo update-ca-certificates

Trust HTTPS certificate on Linux using Edge or Chrome

sudo apt install libnss3-tools
dotnet dev-certs https
sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n localhost -i /usr/local/share/ca-certificates/aspnet/https.crt

Trust the certificate with Firefox on Linux

dotnet dev-certs https
sudo -E dotnet dev-certs https -ep /usr/local/share/ca-certificates/aspnet/https.crt --format PEM
sudo touch /usr/lib/firefox/distribution/policies.json
sudo cat <<EOF | sudo tee /usr/lib/firefox/distribution/policies.json
{
    "policies": {
        "Certificates": {
            "Install": [
                "/usr/local/share/ca-certificates/aspnet/https.crt"
            ]
        }
    }
}
EOF

References
https://docs.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-6.0&tabs=visual-studio#trust-https-certificate-on-linux