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

Working With Query String In ASP.NET Core Blazor

@page "/counter"  
@using Microsoft.AspNetCore.WebUtilities;  
@using Microsoft.Extensions.Primitives;  
@inject NavigationManager navManager  
  
<h1>Counter</h1>  
  
<p>Current count: @currentCount</p>  
  
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>  
  
@code {  
    private int currentCount = 0;  
  
    protected override void OnInitialized()  
    {  
        StringValues initCount;  
        var uri = navManager.ToAbsoluteUri(navManager.Uri);  
        if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("initialCount", out initCount))  
        {  
            currentCount = Convert.ToInt32(initCount);  
        }  
  
    }  
  
    private void IncrementCount()  
    {  
        currentCount++;  
    }  
}

References
https://www.c-sharpcorner.com/article/working-with-query-string-or-query-parameter-in-blazor/
https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing#query-strings

Route Parameters in ASP.NET Core Blazor

@page "/RouteParameter/{text}"

<h1>Blazor is @Text!</h1>

@code {
    [Parameter]
    public string? Text { get; set; }
}

Optional parameters

@page "/RouteParameter/{text?}"

<h1>Blazor is @Text!</h1>

@code {
    [Parameter]
    public string? Text { get; set; }

    protected override void OnInitialized()
    {
        Text = Text ?? "fantastic";
    }
}

Permit app navigation to the same component with a different optional parameter value

protected override void OnParametersSet()
{
    Text = Text ?? "fantastic";
}

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing#route-parameters
https://docs.microsoft.com/en-us/aspnet/core/blazor/components/#route-parameters
https://blazor-university.com/routing/route-parameters/
https://blazor-university.com/routing/optional-route-parameters/