简体   繁体   中英

Why IHttpContextAccessor always get null IP in Blazor server-side?

The SDK I am using is 5.0.100-rc.2.20479.15.

The target framework also is .Net 5.

Here is my code in startup.cs:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

namespace Sample
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();            
            services.AddHttpContextAccessor();            
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }
}

And here is my code in index.razor:

@page "/"
@inject IHttpContextAccessor httpContextAccessor


<h1>@IP</h1>
@code{    
    public string IP{get;set;}
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
          IP=httpContextAccessor.HttpContext.Connection?.RemoteIpAddress.ToString();
        }
    }
}

I published it to the server computer and the IP always returns null.

My program needs to submit a form. And the form is only allowed to submit once per day by the same people(without an account).

So I need to get the IP and set an IMemoryCache with a one-day DateTimeOffset .

In spite, storing the IP address is not a perfect way to solve my feature but it seems I can only do it like this.

The server-side of Blazor Server App communicates with the front-end (Browser) via SignalR, not HTTP. Thus the HttpContext object is not available in Blazor Server App, except on the initial request to the app, which is always an HTTP request. This is the only opportunity when you can access the HttpContext. Note that the _Host.cshtml file is a Razor Page file, so you can put some code in it that access the HttpContext directly, and get whatever data you want to read from the HttpContext, such as the Remote IP, etc. You can then pass the data retrieved to your Blazor SPA as parameters of the component tag helper present in the _Host.cshtml. Add code in the OnInitialized life-cycle method of the App component to get the data, as for instance define a property that gets the remote IP address of the current user. You can then store this data in the local storage for a later use

WARNING: AS @enet comment suggests this is not the recommended way to go about this in Blazor

In case it helps anyone... Here is my interpretation of @Melon NG's suggestion

In _Host.cshtml.cs

using AutoCheck.BlazorApp.Components;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;


namespace AutoCheck.BlazorApp.Pages
{
    public class Host : PageModel
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IRememberMe _rememberMe;

        public Host(IHttpContextAccessor httpContextAccessor, IRememberMe rememberMe)
        {
            _rememberMe = rememberMe;
            _httpContextAccessor = httpContextAccessor;
        }

        public void OnGet()
        {
            _rememberMe.RemoteIpAddress = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress;
            
        }
    }
}

RememberMe

using System.Net;

namespace AutoCheck.BlazorApp.Components
{
    public interface IRememberMe
    {
        public IPAddress RemoteIpAddress { get; set; }
    }

    public class RememberMe : IRememberMe
    {
        public IPAddress RemoteIpAddress { get; set; }
    }
}

About.razor

@page "/About"
@inject IRememberMe RememberMe


<h3>About</h3>

<table class="table table-striped">
    <thead>
    <td>Item</td>
    <td>Value</td>
    </thead>
 
    <tr>
        <td>Remote IP</td>
        <td>@RememberMe.RemoteIpAddress</td>
    </tr>
    
</table>

In ConfigureServices in Startup.cs

public void ConfigureServices(IServiceCollection services)
{
...
//services.AddSingleton<IRememberMe, RememberMe>();
services.AddScoped<IRememberMe, RememberMe>();
...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM