从 IHttpContextAccessor 创建共享 class 以跨 class 库传递它
Create shared class from IHttpContextAccessor to pass it across class libraries
我正在使用 .NET Core 3.1,对于每个请求,我都需要访问一些已记录的用户声明并将其传递给 API 之外的业务服务(另一个 class 库)项目。
我已经尝试创建 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();
其他业务服务或存储库应该 used/injected 像这样:
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 项目。
如果不能,是否可以在控制器中启动 class 从当前用户那里获取所需的信息并将其传递给服务?或者以某种方式在控制器中这样做?
据说我需要自定义 class 以及从业务服务(单独的 class 库)和存储库(单独的 class 库)
中的登录用户获取的信息
这就是我需要访问 BusinessServices 库中记录的用户信息(自定义 UserSession class)的解决方案:
谢谢
IHttpContextAccessor
类型是 ASP.NET 核心框架的一部分,因此仅在您的 Web 项目中可用。如果您的 UsersService
实现在不同的项目中,那么您将无法正确引用上下文访问器。
解决这个问题的一个好方法是将契约与实现分开:在您的库项目中定义一个 IUsersService
,并且只为您的业务逻辑引用它。服务的用户不需要知道实现可能依赖于什么;他们只关心他们可以使用此服务的 public 接口。
然后在您的 Web 项目中,创建一个 IUsersService
的实现,它使用 IHttpContextAccessor
来访问用户信息。由于实现存在于 Web 项目中,因此它可以正确访问上下文访问器。
最后,通过将您的服务实现注册为您的 Web 应用程序的一部分来组合接口和实现:
services.AddTransient<IUsersService, UsersService>();
一旦您的服务(在 Web 项目之外)现在需要 IUsersService
,他们将获得使用上下文访问器访问用户信息的实现,并且一切都应该工作,而无需添加引用到您(否则不相关)库中的 ASP.NET 核心框架。
如果将完整的 dotnetcore 添加到共享解决方案(外部 class 库项目)。只需添加对 Microsoft.AspNetCore.HTTP 的引用即可访问 IHttpContextAccessor
好的,我理解你的担忧,但你似乎以错误的方式解决了问题。
指出来,我相信这就是你想要的:
- 您有
ExampleBusinessService
,它位于共享的 class 库中
- 你有
UsersService
,处理用户会话等服务
- 您想通过
IHttpContextAccessor
访问会话信息
首先,ExampleBusinessService
和 UsersService
都不需要在 API 项目中或与它绑定。您可以随意将它们放入您的 class 图书馆。
您可以通过以下方式解决此问题:
- 首先,在您的 class 库中添加
Microsoft.AspNetCore.Http
包。
- 创建静态 class
UsersService
(在 class 库中)
- 添加以下代码(到
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>();
现在应该一切正常了!!!
我正在使用 .NET Core 3.1,对于每个请求,我都需要访问一些已记录的用户声明并将其传递给 API 之外的业务服务(另一个 class 库)项目。
我已经尝试创建 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();
其他业务服务或存储库应该 used/injected 像这样:
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 项目。
如果不能,是否可以在控制器中启动 class 从当前用户那里获取所需的信息并将其传递给服务?或者以某种方式在控制器中这样做? 据说我需要自定义 class 以及从业务服务(单独的 class 库)和存储库(单独的 class 库)
中的登录用户获取的信息这就是我需要访问 BusinessServices 库中记录的用户信息(自定义 UserSession class)的解决方案:
谢谢
IHttpContextAccessor
类型是 ASP.NET 核心框架的一部分,因此仅在您的 Web 项目中可用。如果您的 UsersService
实现在不同的项目中,那么您将无法正确引用上下文访问器。
解决这个问题的一个好方法是将契约与实现分开:在您的库项目中定义一个 IUsersService
,并且只为您的业务逻辑引用它。服务的用户不需要知道实现可能依赖于什么;他们只关心他们可以使用此服务的 public 接口。
然后在您的 Web 项目中,创建一个 IUsersService
的实现,它使用 IHttpContextAccessor
来访问用户信息。由于实现存在于 Web 项目中,因此它可以正确访问上下文访问器。
最后,通过将您的服务实现注册为您的 Web 应用程序的一部分来组合接口和实现:
services.AddTransient<IUsersService, UsersService>();
一旦您的服务(在 Web 项目之外)现在需要 IUsersService
,他们将获得使用上下文访问器访问用户信息的实现,并且一切都应该工作,而无需添加引用到您(否则不相关)库中的 ASP.NET 核心框架。
如果将完整的 dotnetcore 添加到共享解决方案(外部 class 库项目)。只需添加对 Microsoft.AspNetCore.HTTP 的引用即可访问 IHttpContextAccessor
好的,我理解你的担忧,但你似乎以错误的方式解决了问题。 指出来,我相信这就是你想要的:
- 您有
ExampleBusinessService
,它位于共享的 class 库中 - 你有
UsersService
,处理用户会话等服务 - 您想通过
IHttpContextAccessor
访问会话信息
首先,ExampleBusinessService
和 UsersService
都不需要在 API 项目中或与它绑定。您可以随意将它们放入您的 class 图书馆。
您可以通过以下方式解决此问题:
- 首先,在您的 class 库中添加
Microsoft.AspNetCore.Http
包。 - 创建静态 class
UsersService
(在 class 库中) - 添加以下代码(到
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>();
现在应该一切正常了!!!