从 IHttpContextAccessor 创建共享类以跨类库传递它

问题描述 投票:0回答:4

我正在使用 .NET Core 3.1,对于每个请求,我都需要访问一些记录的用户声明并将其传递给 API 项目外部的业务服务(另一个类库)。

我尝试创建 UserService:

public class UsersService
    {
       private readonly IHttpContextAccessor _context;

       public UsersService(IHttpContextAccessor context)
       {
         _context = context;
       }

    public UserSession GetUser()
    {
        return new UserSession()
        {
            UserDisplayName = _context.HttpContext.User?.Identity?.Name,

        };
    }
}

以及 Startup.cs 中

        public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();

应该由其他业务服务或存储库使用/注入:

    public class ExampleBusinessService
{
    private readonly IUnitOfWork _unitOfWork;
    private IUsersService _userService;
    public ExampleBusinessService(IUnitOfWork unitOfWork, IUsersService userService)
    {
        this._unitOfWork = unitOfWork;
        this._userService = userService;
    }


    

但是,我似乎无法在 Web 项目之外访问 IHttpContextAccessor。

这可以实现吗?

当然,我无法在 API 中创建 UserService,然后在其他库中使用它,因为这些库应该引用 Web 项目。

如果没有,控制器中的启动类是否可以从当前用户获取所需的信息并将其传递给服务?或者以某种方式在控制器中这样做? 据说我需要自定义类,其中包含从业务服务(单独的类库)和存储库(单独的类库)中的登录用户获取的信息

这就是我需要访问 BusinessServices 库中记录的用户信息(自定义 UserSession 类)的解决方案:

谢谢

c# asp.net-core configuration
4个回答
3
投票

IHttpContextAccessor
类型是 ASP.NET Core 框架的一部分,因此仅在您的 Web 项目中可用。如果您在不同的项目中实现了
UsersService
,那么您将无法正确引用上下文访问器。

解决此问题的一个好方法是将合同与实现分开:在您的库项目中定义一个

IUsersService
,并仅在您的业务逻辑中引用它。服务的用户不需要知道实现可能依赖于哪些东西;他们只关心他们可以使用该服务的公共接口。

然后在您的 Web 项目中,创建

IUsersService
的实现,它使用
IHttpContextAccessor
来访问用户信息。由于该实现位于 Web 项目中,因此它可以正确访问上下文访问器。

最后,通过将服务实现注册为 Web 应用程序的一部分来组合接口和实现:

services.AddTransient<IUsersService, UsersService>();

一旦您的服务(Web 项目之外)现在需要

IUsersService
,它们将获得使用上下文访问器来访问用户信息的实现,并且一切都应该正常工作,而无需添加对 ASP.NET Core 的引用您的(否则不相关的)库中的框架。


1
投票

好的,我理解您的担忧,看来您处理问题的方式是错误的。 指出来,我相信这就是你想要的:

  • 您有
    ExampleBusinessService
    ,它驻留在共享类库中
  • 你有
    UsersService
    ,它处理用户会话等服务。
  • 您想通过
    IHttpContextAccessor
  • 访问会话信息

首先,

ExampleBusinessService
UsersService
都不需要位于API项目中或与之绑定。您可以随意将它们放入您的班级库中。

以下是解决此问题的方法:

  • 首先,在你的类库中添加
    Microsoft.AspNetCore.Http
    包。
  • 创建静态类
    UsersService
    (在类库中)
  • 添加以下代码(至
    UsersService
public static class UsersService
{
    // extend IHttpContextAccessor 
    public static UserSession GetUserSession( this IHttpContextAccessor accessor)
    {
         return new UserSession
         {
             UserDisplayName = _context.HttpContext.User?.Identity?.Name,
         }
    }
}
  • 现在,在您的
    ExampleBusinessService
    中注入
    IHttpContextAccessor
public class ExampleBusinessService
{
    private readonly IHttpContextAccessor _contextAccessor;

    public ExampleBusinessService(IHttpContextAccessor accessor)
    {
        _contextAccessor = accessor,
    }

    // now do whatever you want with the session info
    public SomeBusinessAboutSessionInfo()
    {
        // retrieve the session
        var userSession = _contextAccessor.GetUserSession();
        //...your logic
    }
}

最后一块(这很重要

  • IHttpContextAccessor
    添加到 API 项目中的
    IServiceCollection

services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();

现在一切都应该解决了!!!


0
投票

如果您需要引用 AspNet Core 框架中的任何内容,您必须选择:

  1. 目标
    Microsoft.NET.Sdk.Web
  2. 将显式
    FrameworkReference
    添加到
    Microsoft.AspNetCore.App
<Project Sdk="Microsoft.NET.Sdk.Razor">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
    ...
</Project>

参考


-1
投票

如果将完整的 dotnetcore 添加到共享解决方案(外部类库项目)。只需添加对 Microsoft.AspNetCore.HTTP 的引用即可访问 IHttpContextAccessor

© www.soinside.com 2019 - 2024. All rights reserved.