In Blazor versions 6/7 I can get the remote IP address in _Host.cshtml with:
@inject ILogger<Pages__Host> Logger
RemoteIp = HttpContext.GetRemoteIpAddress(Logger);
But this does not work in App.razor in version 8. So how can I get this in version 8?
A simple service:
public class IPAddressService
{
public const string TokenName = "IPAddress";
public string RemoteIpAddress { get; set; } = "Not Set";
}
Register Services:
builder.Services.AddScoped<IPAddressService>();
Get the IpAddress and persist it in App.razor
@implements IDisposable
@using SO78174146.Components.Pages
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="SO78174146.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet @rendermode="InteractiveServer" />
</head>
<body>
<Routes @rendermode="InteractiveServer" />
<script src="_framework/blazor.web.js"></script>
</body>
</html>
@code{
[CascadingParameter] HttpContext? HttpContext { get; set; }
[Inject] public PersistentComponentState ApplicationState { get; set; } = default!;
private PersistingComponentStateSubscription? _persistingSubscription;
private bool _subsequentRender;
private string RemoteIpAddress = "Not Set";
protected override void OnInitialized()
{
this.RemoteIpAddress = this.HttpContext?.Connection.RemoteIpAddress?.ToString() ?? "Not Set";
_persistingSubscription = ApplicationState.RegisterOnPersisting(this.PersistData);
}
public Task PersistData()
{
this.ApplicationState.PersistAsJson<string>(IPAddressService.TokenName, this.RemoteIpAddress);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
_persistingSubscription?.Dispose();
}
}
A Component to get the persisted IPAddress using Persisting Component State.
public class IPAddressGrabber : ComponentBase
{
[Inject] public IPAddressService IPAddressService { get; set; } = default!;
[Inject] public PersistentComponentState ApplicationState { get; set; } = default!;
private bool _subsequentRender;
private const string TokenName = "IPAddress";
private string RemoteIpAddress = "Not Set";
// Short circuit all the lifecycle stuff - we don't need it
public override Task SetParametersAsync(ParameterView parameters)
{
if (_subsequentRender)
return Task.CompletedTask;
// if not prerender, try and get the persisted value
if (this.ApplicationState.TryTakeFromJson<string>(IPAddressService.TokenName, out var address))
{
this.RemoteIpAddress = address ?? "Not Set";
this.IPAddressService.RemoteIpAddress = this.RemoteIpAddress;
}
_subsequentRender = true;
return Task.CompletedTask;
}
}
Add it to Routes
<IPAddressGrabber />
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
Demo Page:
@page "/"
@inject IPAddressService IpAddressService
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<div class="bg-dark text-white" m-2 p-2>
<pre>IpAddress: @(IpAddressService.RemoteIpAddress.ToString())</pre>
</div>