Search code examples
asp.net-coreasp.net-web-apiblazor-webassembly

NavManager.NavigateTo(); 404 status code under phone usage


I got a problem with NavManager.NavigateTo(); for Blazor webassembly application The scenario is the following:

I have a drop-down menu with possible website language translations and when the user wants to change the website language he should access a Web API controller action which will set the culture into the website cookies via the drop-down menu. Let me share some code.

Here is the UI part from the Razor component

<div class="languageChanger">  
    <select class="form-select" @bind="this.Culture">
        @foreach (var culture in cultures)
        {
            <option value="@culture">@this.Localizer[culture.Name]</option>
        }
    </select>
</div>

And here is the C# code part ot the Razor Component

CultureInfo[] cultures = new[]
{
    new CultureInfo("en-US"),
    new CultureInfo("bg-BG")
};

public CultureInfo Culture
{
    get => CultureInfo.CurrentCulture;
    set
    {
        if (CultureInfo.CurrentCulture != value)
        {
            var js = (IJSInProcessRuntime)this.JsRuntime;
            js.InvokeVoid("SimeonValevPortfolioCulture.set", value.Name);

            var uri = new Uri(this.NavManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
            var query = $"?cultureName={Uri.EscapeDataString(value.Name)}&" + $"redirectUri={Uri.EscapeDataString(uri)}";

            this.NavManager.NavigateTo($"api/Culture/SetCulture" + query, forceLoad: true);
        }
    }
}

And here is the API Controller action

[HttpGet]
public IActionResult SetCulture(string cultureName, string redirectUri)
{
    if (cultureName != null)
    {
        this.HttpContext.Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(
                new RequestCulture(cultureName)), new CookieOptions()
                {
                    Expires = DateTimeOffset.UtcNow.AddMonths(1),
                });
    }

    return this.LocalRedirect(redirectUri);
}

When I run the application locally, the controller action is accessed correctly and also when I deployed the application, the api action is correctly accessed from Google Chrome under Windows 10 OS. But via phone, under Android(Chrome web browser) and iOS(Safari web browser) the user is not able to access the API action. When he try to change the website culture the only thing which he can get from that operation is 404 status code. I noticed that when he try to update the drop-down value, he receive the following URL into the browser:

https://MySiteName.com/api/Culture/SetCulture?cultureName=bg-BG&redirectUri=%2F

And after that the application returns 404 status code

The conclusion which I get is somehow the api action could not be accessed only from phones. The issue is not faced under laptop usage.

Please let me know is there something which I missed.

Regards, Simeon Valev

P.S. If it will be much better for you, I can share the website URL, it is hosted. Let me know


Solution

  • I fix the issue by creating a standard GET request. I apply the code changes. Now it work properly.

    @code {
        private string currentCulture;
    
        CultureInfo[] cultures = new[]
            {
            new CultureInfo("en-US"),
            new CultureInfo("bg-BG")
        };
    
        protected override async Task OnInitializedAsync()
        {
            this.currentCulture = CultureInfo.CurrentCulture.Name;
            await base.OnInitializedAsync();
        }
    
        public async Task OnCultureChanged(ChangeEventArgs e)
        {
            var cultureName = e.Value.ToString();
            var js = (IJSInProcessRuntime)this.JsRuntime;
            js.InvokeVoid("SimeonValevPortfolioCulture.set", cultureName);
            var response = await this.HttpClient.GetFromJsonAsync<CompletedOperationViewModel>($"api/Culture/SetCulture/{cultureName}");
            this.NavManager.NavigateTo(this.NavManager.Uri, forceLoad: true);
            await response.DisplayMessage(this.JsRuntime);
        }
    }