How to use the HttpContext object in server-side Blazor to retrieve information about the user, user agent
The fiction that the HttpContext
object can't be used with Blazor Server App, has been long propagated on Stackoverflow, and it is high time to pension it off.
It is true that the HttpContext
is not available when a WebSocket connection is in operation, but this must be clear: When you type an url and press the enter button, the connection to your server-side Blazor app is an HTTP connection, and not a WebSocket connection.
Thus, your app can access and use the HttpContext
in the same way it is used in a Razor Pages App or a MVC App, including getting the User Agent and an IP Address. The following code sample demonstrates how to use the HttpContext
to get the User Agent and IP Address natively, without using JSInterop
which should be used as a last resort, and pass the extracted values to the App
component.
- Add a file to the
Pages
folder and name it_Host.cshtml.cs
. - Add this code to the file:
public class HostModel: PageModel
{
private readonly IHttpContextAccessor _httpContextAccssor;
public HttpContextFeatureModel(IHttpContextAccessor httpContextAccssor)
{
_httpContextAccssor = httpContextAccssor;
}
public string UserAgent { get; set; }
public string IPAddress { get; set; }
// The following links may be useful for getting the IP Adress:
// https://stackoverflow.com/questions/35441521/remoteipaddress-is-always-null
// https://stackoverflow.com/questions/28664686/how-do-i-get-client-ip-address-in-asp-net-core
public void OnGet()
{
UserAgent = _httpContextAccssor.HttpContext.Request.Headers["User-Agent"];
// Note that the RemoteIpAddress property returns an IPAdrress object
// which you can query to get required information. Here, however, we pass
// its string representation
IPAddress = _httpContextAccssor.HttpContext.Connection.RemoteIpAddress.ToString();
}
}
You may need one or more of these usings:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
- Add the following line to your
Host.cshthml
page (on top of the page near to the usings and that stuff):
@model HostModel
- In the
App
component, define two parameter properties that will get and store the User Agent and IP Address passed to it from the component tag located in_Host.cshtml
.
App.razor:
<p>UserAgent: @UserAgent</p>
<p>IPAddress: @IPAddress</p>
@code
{
[Parameter]
public string UserAgent { get; set; }
[Parameter]
public string IPAddress { get; set; }
}
- In
_Host.cshtml
update the component tag like this (This method is outdated now):
<app>
<component type="typeof(App)" render-mode="ServerPrerendered" param-UserAgent="@Model.UserAgent" param-IPAddress="@Model.IPAddress" />
</app>
In current Blazor server side apps, this can be done like this:
<div>
@(await Html.RenderComponentAsync<App>(RenderMode.Server, new { IPAddress = Model.IPAddress, UserAgent = Model.UserAgent }))
</div>
- Add
services.AddHttpContextAccessor();
toStartup
'sConfigureServices
method to enable access to the HttpContext.
That is all. You can add the Identity UI
to your Blazor Server App as well and apply the same procedure shown above to extract the claims principal from the HttpContext
, after the user has authenticated (do that for learning purpose only, as you should use the AuthenticationStateProvider instead).
Here's also a link to a question I've just answered about setting the consent cookie in a Blazor Server App.