Component Virtualization in ASP.NET Core Blazor

Virtualization is a technique that helps you to process and render only the items that are currently visible on the page (in the content viewport). We can use this technique when dealing with large amounts of data, where processing all the data and displaying the result will take time.

<div style="height:400px; overflow-y:scroll">
    <Virtualize Items="@allBooks">
        <BookSummary @key="book.BookId" Details="@book.Summary" />
    </Virtualize>
</div
<Virtualize Context="employee" ItemsProvider="@LoadEmployees">
    <p>
        @employee.FirstName @employee.LastName has the 
        job title of @employee.JobTitle.
    </p>
</Virtualize>
<Virtualize Context="employee" Items="@employees" ItemSize="25">
    ...
</Virtualize>
<Virtualize Context="employee" Items="@employees" OverscanCount="4">
    ...
</Virtualize>

References
https://docs.microsoft.com/en-us/aspnet/core/blazor/components/virtualization?view=aspnetcore-6.0
https://www.syncfusion.com/blogs/post/7-features-of-blazor-that-make-it-an-outstanding-framework-for-web-development.aspx/amp
https://www.syncfusion.com/blogs/post/asp-net-core-blazor-component-virtualization-in-net-5.aspx

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