Skip to main content

Unveiling the Challenges of Blazor Development: Navigating Through Insufficient Libraries and Unstable Experiences

I have shipped six Blazor products — Server, WASM, and MAUI — and I genuinely like the technology. But the gap between the promise and the day-to-day reality is real, and most articles about Blazor do not talk about it honestly. This one does.

Hello, first of all, I should tell you that I have been developing projects for more than 7 years and I really enjoyed blazor. 2 server product, 2 wasm product, 2 maui product i developed. I would like to share the problems I have experienced in general.

Begining #

Initial impression may be positive, but as development progresses, serious problems can arise. I’ve developed two applications using Blazor Server, Blazor WASM, and Blazor MAUI.

VSCode Or Visual Studio #

Encountering issues with vscode and intellisense is a major concern. At times, the components you define and accessible components may appear as errors, although there are no errors during the build and the project functions correctly. This discrepancy can be confusing, and some correct code may appear incorrect, leading to ignoring these errors.

Blazor Server #

The authentication process in Blazor Server is troublesome because the entire application runs over the signalr socket. When the socket connection is lost, the user is also disconnected (e.g., page refresh, opening in a new tab).

To address this, storing the user’s claim model in the browser’s session storage with protected storage can solve the refresh problem. However, writing your own authentication middleware is necessary. If you want to open a separate signalr hub in your Blazor Server project and use it, you need to specify another authentication method because the socket connection does not reach the user. To overcome this, I resolved the issue by using authentication in ticket logic with JWT.

Additionally, rendering can become challenging since authentication is rendered in the browser while the component is rendered on the server. This requires rendering each component twice, with the first rendering lacking authentication. Authentication is dynamically retrieved from the browser at the end of the first render using JavaScript in the background and rendered again. This might explain why the component sometimes works and sometimes doesn’t. In some cases, you might need to use while in others, manually checking the service injection in an extra component is necessary. also @attribute [Authorize] this is not working sometimes too. It’s important to note that these problems cannot be completely solved with JWT or OAuth. Furthermore, there have been instances where the code provided in Microsoft’s documentation didn’t work, such as in the case of creating an in-memory state container service MSDN ASP.Net Core 7 In-memory state container service, where the direct statechanged method on the component side didn’t work as shown in the example. The solution is to write a separate handler:

private async void OnMyChangeHandler()
{
    await InvokeAsync(() => {
        StateHasChanged();
    });
}

Unfortunately, what works in one place may not work in another. Communication issues between the browser and itself during the rendering process, along with the lack of sufficient NuGet packages, make accessing certain browser APIs difficult.

Razor #

If the initial parameter in many components is empty due to the component’s lifetime, it becomes necessary to implement checks and controls during rendering. However, this approach may appear somewhat hacky and not ideal from a coding standpoint.

Writing code like the following at the beginning of a component is not ideal:

if (mylist == null) {
    return;
} else if (mylist.Any()) {
    <NoItemComponent/>
    return;
} 
    /// Your Component Starts Here 

To avoid this, you can consider checking and calling the component where it’s invoked, passing the complete list directly. However, personally, I prefer a more dynamic approach by passing the required data as a parameter and retrieving it from an injected service within the component. Unfortunately, after the OnParametersSetAsync method, the list becomes null, necessitating a preliminary check.

Ideally, i wish we could handle this directly with directives, similar to Angular. For example:

<div @foreach="mylist">
    // code
</div>

<div @if="">
    // Some Codes
</div>

When we do it this way and define the list as nullable, we should be able to continue our operations without any errors. Of course, if it is not null, we will have control, but since these operations take place asynchronously after pulling the data, it will provide a more controlled development opportunity without errors in the component rendering parts. It is better to have the parts under my control after pulling or pulling the data. It is really sad to resort to tricks like this so that the component does not get a direct error while loading.

Blazor WASM #

While some of these problems are alleviated when switching to Blazor WASM since it works entirely in the browser, new issues arise, particularly with async multi-thread operations due to browser limitations. The in-memory state container service problem persists here as well. Additionally, since it’s a single-page application (SPA), extensive code separation with the API becomes necessary for security purposes, which I also coding this way generally.

Blazor MAUI #

Now, let’s discuss Blazor MAUI. Reusing components from the web application is great, but it’s also the most unstable part. It’s unbelievable that the project may not even compile when you open it after a week. Signing is a painful process, and even following the documentation precisely, you may need to compile it using the terminal. Unfortunately, whatever you try in the options section or csproj doesn’t provide a solution. I’ve compiled and published the application for both Android and iOS, and both were challenging experiences, particularly the iOS part. Signing is already laborious, and although I understand this, there is no clear solution to learn from. You can try methods mentioned in the documentation, YouTube, or Stack Overflow, but none of them are guaranteed to work, and you may encounter problems with all of them.

In reality, signing problems are not limited to Blazor but this is the worst i ever seen.

To summarize; #

  • Insufficient libraries.
  • An unstable IDE.
  • Code that may work one day but not the next.
  • Examples provided in documentation that may not work in practice.

These issues generate feelings of insecurity during the development of a enterprise product and may drive you towards considering an alternative framework.