【问题标题】:HttpContextAccessor is nullHttpContextAccessor 为空
【发布时间】:2023-02-21 03:08:32
【问题描述】:

首先,如果这个话题已经被讨论过,我很抱歉。我无法在网上找到我想要的东西,所以这就是我这样做的原因。

标题解释得很好,当我尝试访问它时,HttpContextAccessor 为空。 我在 Program.cs 中注册了这样的服务:

builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddScoped<CustomStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<CustomStateProvider>());

我正在使用它在身份验证时将用户数据保存在 cookie 中。

我在 CustomStateProvider 类中注入了 IHttpContextAccessor :

[Inject]
public IHttpContextAccessor HttpContextAccessor { get; set; }

但是,当我启动该应用程序时,我在这一行收到 System.NullReferenceException:

var cookie = HttpContextAccessor.HttpContext.Request.Cookies["CurrentUser"];

这是完整的 CustomStateProvider 类:

public class CustomStateProvider : AuthenticationStateProvider
    {
        [Inject]
        public IHttpContextAccessor HttpContextAccessor { get; set; }

        private readonly IAuthService _authService;

        private CurrentUser _currentUser;

        public CustomStateProvider(IAuthService authService)
        {
            this._authService = authService;
        }

        public override async Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            var identity = new ClaimsIdentity();
            try
            {
                var userInfo = GetCurrentUser();
                if (userInfo.IsAuthenticated)
                {
                    var claims = new[] { new Claim(ClaimTypes.Name, _currentUser.UserName) }.Concat(_currentUser.Claims.Select(c => new Claim(c.Key, c.Value)));
                    identity = new ClaimsIdentity(claims, "Server authentication");
                }
            }
            catch (HttpRequestException ex)
            {
                Console.WriteLine("Request failed:" + ex);
            }

            return new AuthenticationState(new ClaimsPrincipal(identity));
        }

        public async Task Login(ConnexionModel loginParameters)
        {
            _authService.Login(loginParameters);

            // No error - Login the user
            var user = _authService.GetUser(loginParameters.UserName);
            _currentUser = user;
            var cookieOptions = new CookieOptions
            {
                Expires = DateTime.Now.AddDays(7),
                HttpOnly = true
            };
            HttpContextAccessor.HttpContext.Response.Cookies.Append("CurrentUser", JsonConvert.SerializeObject(_currentUser), cookieOptions);
            NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
        }

        public async Task Logout()
        {
            _currentUser = null;
            HttpContextAccessor.HttpContext.Response.Cookies.Delete("CurrentUser");
            NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
        }

        public async Task Register(InscriptionModel registerParameters)
        {
            _authService.Register(registerParameters);

            // No error - Login the user
            var user = _authService.GetUser(registerParameters.UserName);
            _currentUser = user;
            var cookieOptions = new CookieOptions
            {
                Expires = DateTime.Now.AddDays(7),
                HttpOnly = true
            };
            HttpContextAccessor.HttpContext.Response.Cookies.Append("CurrentUser", JsonConvert.SerializeObject(_currentUser), cookieOptions);
            NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
        }

        public CurrentUser GetCurrentUser()
        {
            if (_currentUser != null && _currentUser.IsAuthenticated)
            {
                return _currentUser;
            }
            else
            {
                var cookie = HttpContextAccessor.HttpContext.Request.Cookies["CurrentUser"];
                if (cookie != null)
                {
                    return JsonConvert.DeserializeObject<CurrentUser>(cookie);
                }
            }

            return new CurrentUser();
        }
    }
}

我想我没有正确注册服务,我尝试弄乱 Program.cs 但无法解决问题。我对 Blazor 很陌生,所以我对这类东西了解不多。

感谢您的帮助。

【问题讨论】:

    标签: c# service blazor blazor-server-side


    【解决方案1】:

    IHttp上下文on Blazor Server 仅在加载 Blazor Server 应用程序时的第一个 Http 请求上可用。之后,所有与服务器的连接都通过 SignalR 处理。在此之后,您的 HttpContext 很可能为空。根据你运行的 Blazor Server 版本,你需要找到在应用程序树中呈现的第一个文件。

    但是,您可以将用户详细信息保存到 cookie 中,因为 Blazor Server 是有状态的,我建议您在整个应用程序生命周期中通过级联参数保存它。

    在我正在开发应用程序的 Blazor Server 版本中,我有两个文件:

    • _Host.cshtml
    • App.razor

    _Host.cshtml 是我可以访问的地方IHttp上下文如果它不为空,我将所有这些值存储到用户对象并通过级联参数将其持久化到应用程序中。在我的实例中,我使用的是 Windows 身份验证,但您可以将此方法用于任何类型的身份验证。

    _Host.cshtml

    @page "/"
    @namespace oms.net.Pages
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @using Core.Identity.User
    @using Microsoft.AspNetCore.Components.Web
    @inject IUserRepository User
    @{
        Layout = null;
    }
    
    @{
        var userObject = await User.GetUserDetailsAsync(User.GetCurrentUserName());
        if(userObject != null)
        {
        <!DOCTYPE html>
        <html lang="en">
        <head>
                    <meta charset="utf-8" />
                    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                    <title></title>
                    <base href="~/" />
                    <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
                    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">      
        </head>
        <body>
    //this is key for persisting the user object as a cascading parameter
                    <component type="typeof(App)" render-mode="ServerPrerendered" param-UserObject = "@userObject"/>
                 
                    <div id="blazor-error-ui">
                        <environment include="Staging,Production">
                            An error has occurred. This application may no longer respond until reloaded.
                        </environment>
                        <environment include="Development">
                            An unhandled exception has occurred. See browser dev tools for details.
                        </environment>
                        <a href="" class="reload">Reload</a>
                        <a class="dismiss">?</a>
                    </div>
                    <script src="_framework/blazor.server.js"></script>      
        </body>
        </html>
        }
        else
        {
        <b>Invalid user, contact support. The user may need to be added to []</b>
        <i>Your Active Directory username may not match your produce pro credentials. If this is the case, please inform IT.</i>
        }
    }
    

    应用程序剃刀

    @using Core.Identity.User
    @using Core.Identity.Models
    
    <CascadingAuthenticationState>
        <CascadingValue Value="userObject">
        <Router AppAssembly="@typeof(Program).Assembly">
            <Found Context="routeData">
                <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            </Found>
            <NotFound>
                <LayoutView Layout="@typeof(MainLayout)">
                    <p></p>
                </LayoutView>
            </NotFound>
        </Router>
        </CascadingValue>
    </CascadingAuthenticationState>
    
    @code {
        [Parameter]
        public UserModel userObject { get; set; }
    }
    

    在 Razor 组件中访问级联参数的示例:

    [CascadingParameter]
    private UserModel User { get; set; }
    

    这是我创建的更详细的解释:https://www.raynorsystems.com/null-ihttpcontextaccessor-blazor-server/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-15
      相关资源
      最近更新 更多