Search code examples
blazorblazor-server-side

How do I get the Remote IP address in Blazor version 8


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?


Solution

  • 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>