Blazor 8.0 NavigateTo throws an exception

Kuler Master 306 Reputation points
2024-12-19T08:59:18.7133333+00:00

Hello,

I have a language selector that calls the following code and it works like a charm.

On other hand, I want to change the language from within the MainLayout on Initialized event (async) but then the very same code throws an exception of type NavigationException. No further explanation.

var cultureEscaped = languageFromURL == "en" ? "en-US" : "de-DE"; 
_navigationManager.NavigateTo($"Culture/Set?culture={cultureEscaped}&redirectUri=/");

The Culture is Controller and Set is an action.

The idea is to change the language if the language in the URL differs from the CultureInfo language. Maybe I should use another component instead of MainLayout? Please advice.

Thank you!

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,704 questions
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,636 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,152 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Kuler Master 306 Reputation points
    2024-12-23T07:53:13.7166667+00:00

    This is the code that I have at the moment and which throws that exception explained previously.

    protected override async Task OnParametersSetAsync()
    {
    
        var languageFromURL = string.Empty;
        var languageFromCulture = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
        var parts = _navigationManager.ToBaseRelativePath(_navigationManager.Uri.ToString()).Split('/');
    
        if (parts.Count() > 1)
        {
            languageFromURL = parts[0];
    
            PageName = parts[1];
        }
    
    
        try
        {
            // ensure that language is two letters
            if (languageFromCulture.Length == 2 && languageFromURL.Length == 2)
            {
                if (languageFromURL != languageFromCulture)
                {
                    //-- LANGUAGE IN THE URL DIFFERS FROM THE CURRENTLY SELECTED LANGUAGE
    
                    var isPastedRouteFound = false;
                    var newLanguage = string.Empty;
                    var newRoute = string.Empty;
    
                    using (Microsoft.Data.SqlClient.SqlConnection connection = DatabaseHelpers.NewConnection())
                    {
                        connection.Open();
                        using (Microsoft.Data.SqlClient.SqlCommand command = connection.CreateCommand())
                        {
                            command.CommandType = System.Data.CommandType.StoredProcedure;
                            command.CommandText = "blazor_CheckRoute";
                            command.Parameters.AddWithValue("@LanguageFromCulture", languageFromCulture); // language from the culture info
                            command.Parameters.AddWithValue("@LanguageFromURL", languageFromURL); // language from the route/URL
                            command.Parameters.AddWithValue("@PageName", PageName);
                            command.Parameters.Add("@IsRouteFound", System.Data.SqlDbType.Int, 4).Direction = System.Data.ParameterDirection.Output;
                            command.ExecuteNonQuery();
                            if (command.Parameters["@IsRouteFound"].Value != null)
                            {
                                isPastedRouteFound = Convert.ToBoolean(command.Parameters["@IsRouteFound"].Value);
                            }
                        }
                    }
    
                    if (isPastedRouteFound == true)
                    {
                        var culture = string.Empty;
                        switch (languageFromURL)
                        {
                            case "en":
                                culture = Uri.EscapeDataString("en-US");
                                break;
                            case "de":
                                culture = Uri.EscapeDataString("de-DE");
                                break;
                            case "es":
                                culture = Uri.EscapeDataString("es-ES");
                                break;
                        }
    
    
                        _httpContextAccessor.HttpContext.Response.Cookies.Append(
                            CookieRequestCultureProvider.DefaultCookieName,
                            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture, culture)));
    
                        //-- EXCEPTION IS THROWN WHEN THE LINE BELOW GETS EXECUTED
                        //_navigationManager.NavigateTo(_navigationManager.Uri, true);
    
                    }
    
                }
            }
    
        }
        catch (Exception ex)
        {
            Logging.LogError(ex, remark: "");
        }
    
        await Task.CompletedTask;
    }
    
    

    Database Table (Pages)

    Language Route

    en contact

    de kontakt

    es contacto

    etc. etc.

    Possible scenario: let's say you are currently visiting website.com/es/contacto. Then you paste the following URL to the address bar and hit enter: website.com/en/contact. It redirects you to the new route but the page remains in Spanish. Then if you navigate to another page the language gets changed to EN.

    I am certain that I miss something obvious though I am not quite sure what. Thank you!

    0 comments No comments

  2. Bruce (SqlWork.com) 68,486 Reputation points
    2024-12-23T17:19:00.79+00:00

    as you are calling NavigateTo during render it has to throw an error to stop processing (much like aborting a task). don't catch the error, or use OnAfterRender()

    also can not update the cookie, as httpcontext is readonly in a blazor app. the request created the signal/r connection and there is no response available. you should handle this logic before the blazor app starts with middleware.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.