OK, got it. I could delete the question, but maybe someone would stumble upon the similar problem.
First things first:
How to use the HttpContext object in server-side Blazor to retrieve information about the user, user agent
Here's what I've started from. I needed to detect a mobile device, it worked as charm (with a few modifications, irrelevant now).
The important part is that _Host.cshtml.cs
example. In the link I pasted there is description how to access the HttpContext
of the request. And one more important thing - how to pass parameters from the host to the main App.razor
component.
So I just wondered - what if I made a redirection there, in the App?
So, my App:
using Microsoft.AspNetCore.Components;
using System;
namespace Example {
public partial class App : IDisposable {
[Inject] NavigationManager NavMan { get; set; }
[Parameter] public bool IsMobile { get; set; }
void LocationChangeEventHandler(object sender, EventArgs eventArgs) => ScriptableComponentBase.ResetInstanceCounter();
protected override void OnInitialized() {
base.OnInitialized();
NavMan.LocationChanged += LocationChangeEventHandler;
var localPath = new Uri(NavMan.Uri).LocalPath;
if (IsMobile && localPath == "/") NavMan.NavigateTo("/m_index");
}
public void Dispose() => NavMan.LocationChanged -= LocationChangeEventHandler;
}
}
Holup... How do I get IsMobile
parameter?
Here, my relevant _Host.cshtml
fragment:
<app>
<component type="typeof(App)" render-mode="ServerPrerendered" param-IsMobile="@Model.IsMobile" />
</app>
Wait, but where does the Model
come from? From the linked example. Here's mine _Host.cshtml.cs:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Components;
namespace Example.Pages {
/// <summary>
/// Allows access HttpContext to detect mobile requests.
/// <see href="https://stackoverflow.com/questions/59538318/how-to-use-the-httpcontext-object-in-server-side-blazor-to-retrieve-information" />
/// </summary>
public class HostModel : PageModel {
private readonly IHttpContextAccessor _httpContextAccssor;
private readonly Regex RxMobileUATest = new Regex(@"(iPhone|Android|Mini|Mobile|Puffin)", RegexOptions.Compiled);
public HostModel(IHttpContextAccessor httpContextAccssor, NavigationManager navigationManager) => _httpContextAccssor = httpContextAccssor;
public string UserAgent { get; private set; }
public string IPAddress { get; private set; }
public bool IsMobile { get; private set; }
public void OnGet() {
UserAgent = _httpContextAccssor.HttpContext.Request.Headers["User-Agent"];
IPAddress = _httpContextAccssor.HttpContext.Connection.RemoteIpAddress.ToString();
IsMobile = RxMobileUATest.IsMatch(UserAgent);
}
}
}
It all looks a little bit chaotic, but it shows the direction of my investigation. First I've checked if I can redirect the main page ("/" request) to a random other page in the App
component. To my greatest surprise I could. The rest seemed to be easy having the knowledge from the link. So - I needed my app to know, if the request comes from a mobile browser. I've seen in linked example, that a parameter can be passed to the App
component. I just needed to get the value. So I needed to access HttpContext
of the request to get the headers from the browser, that can be done like in linked example: basically you create a model for the _Host.cshtml
page. You have also to add services.AddHttpContextAccessor();
to your Startup.ConfigureServices()
method. Having the context - detecting the mobile browsers by UserAgent
header is a piece of cake. You can totally ignore all weird cases. If a mobile browser doesn't want mobile content - fine, we serve desktop. If the mobile browser doesn't want to announce it's a mobile browser like most mobile browsers do - we serve desktop.
Look mum, no JavaScript! ;)