简体   繁体   English

如何在 ASP.Net Core 服务层的基础 class 中获取当前用户?

[英]How to get current User in base class of service layer in ASP.Net Core?

There are answers how to get User principal in service layer using IHttpContextAccessor but they are always related to getting the user in service itself, not in its base (abstract class).有如何使用IHttpContextAccessor在服务层中获取用户主体的答案,但它们始终与让用户进入服务本身有关,而不是在其基础(抽象类)中。

I have following situation:我有以下情况:

There is an UserService which is injected in controller which needs it like this:在 controller 中注入了一个UserService ,它需要这样:

private IUserService UserService;
public UserController(IUserService userService)
{
    UserService = userService;
}

Pretty standard, this is service layer for getting/posting/patching... user.非常标准,这是用于获取/发布/修补...用户的服务层。 Problem is, this UserService inherits something called ServiceBase :问题是,这个UserService继承了一个叫做ServiceBase的东西:

public class UserService : ServiceBase, IUserService
{
    private IDatabaseService DatabaseService;
    public UserService(IDatabaseService databaseService, ServiceManager serviceManager) : base(serviceManager)
    {
        DatabaseService = databaseService;
    }
.. rest of code omitted ...

and ServiceBase looks like this:ServiceBase看起来像这样:

public abstract class ServiceBase
{
    internal static readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();
    private ServiceManager ServiceManager;

    public ServiceBase(ServiceManager serviceManager)
    {
        ServiceManager = serviceManager;
    }
 ... rest of code omitted...

Now, if I wanted to use IHttpContextAccessor I would have to inject it in each of services so it can be passed to ServiceBase , much like ServiceManager (another singleton service, not related to this question) is passed to it.现在,如果我想使用IHttpContextAccessor我必须将它注入到每个服务中,以便它可以传递给ServiceBase ,就像传递给它的ServiceManager (另一个 singleton 服务,与这个问题无关)一样。 Reason why ServiceBase is needed is for logging and more importantly, providing a way for each of services to post changes made by them (post, patch, delete) to rest of microservices.需要ServiceBase的原因是用于日志记录,更重要的是,为每个服务提供一种将它们所做的更改(发布、修补、删除)发布到微服务的 rest 的方法。

Startup looks like this:启动看起来像这样:

 services.AddSingleton<ServiceManager>();
 services.AddHostedService(provider => provider.GetService<ServiceManager>());

 services.AddHttpContextAccessor();
 services.AddScoped<IDatabaseService, DatabaseService>();
 services.AddScoped<ILoginService, LoginService>();
 services.AddScoped<IUserService, UserService>();

Is there a way to get IHttpContextAccessor in this ServiceBase without passing it around?有没有办法在这个ServiceBase中获取IHttpContextAccessor而无需传递它? Same question could be asked for ServiceManager since that dependancy also has to be passed from implementation to base class?可以对ServiceManager提出同样的问题,因为依赖关系也必须从实现传递到基础 class? What I want is to know which user did call the controller action (and consequently the service layer) without writing bunch of boilerplate code in each of controllers and/or services.我想知道哪个用户确实调用了 controller 操作(以及服务层),而无需在每个控制器和/或服务中编写一堆样板代码。

Another way of asking would be is it possible to resolve singleton services like IHttpContextAccessor and ServiceManager inside service layer without injecting them in each service?另一种询问方式是是否可以在服务层内部解决 singleton 服务(如IHttpContextAccessorServiceManager )而不在每个服务中注入它们?

Short answer: You can't.简短的回答:你不能。

Bad answer: You shouldn't.错误的答案:你不应该。 But you can with a ServiceLocator . 但是您可以使用 ServiceLocator

Alternate answer: we can make the paramter transfer less pain.替代答案:我们可以使参数传输不那么痛苦。

Instead of passing ServiceManager to the base class, pass a ServiceBaseServiceContext to it:不要将ServiceManager传递给基础 class,而是将ServiceBaseServiceContext传递给它:

public class ServiceBaseServiceContext
{
    public ServiceManager ServiceManager {get;}
    public IUserService UserService {get;}

    public ServiceBaseServiceContext(ServiceManager serviceManager, IUserService userService)
    {
        ServiceManager = serviceManager;
        UserService = userService;
    }
}

This way, you have only one Parameter, regardless how many services you need.这样,无论您需要多少服务,您都只有一个参数。

public abstract class ServiceBase
{
    private ServiceManager _serviceManager;
    private IUserService_userService;

    public ServiceBase(ServiceBaseServiceContext serviceContext)
    {
        _serviceManager = serviceContext.ServiceManager;
        _userService = serviceContext.UserService;
    }
}

ServiceBaseServiceContext needs also to be registered in your ServiceCollection to make it work: ServiceBaseServiceContext还需要在您的 ServiceCollection 中注册以使其工作:

// depending on the services maybe Scoped
services.AddTransient<ServiceBaseServiceContext>();

Instead of making a ServiceBaseServiceContext you could also pass a IServiceProvider to ServiceBase , but this would be the same as a ServiceLocator, which is bad, because it hides the dependencies.除了创建ServiceBaseServiceContext之外,您还可以将IServiceProvider传递给ServiceBase ,但这与 ServiceLocator 相同,这很糟糕,因为它隐藏了依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在ViewComponent Asp.Net Core中获取当前登录用户 - How get current login user in ViewComponent Asp.Net Core asp.net core中如何获取当前用户 - How to get current user in asp.net core ASP.NET Core Identity - 获取当前用户 - ASP.NET Core Identity - get current user 从ASP.NET CORE 2获取当前用户 - Get Current User From ASP.NET CORE 2 在 ASP.NET Core 中进行服务配置时如何获取基本路由? - How can I get the base route while doing service configuration in ASP.NET Core? 如何将当前用户会话信息从 Web 应用程序传递到 asp.net core 中的业务层 - How do I pass current user session information from web application to business layer in asp.net core 如何在 ASP.NET Core 中删除当前用户的声明? - How to remove claims from current user in ASP.NET Core? 如何使用 ASP.NET Core RC2 MVC6 和 IIS7 获取当前的 Windows 用户 - How to get the current Windows user with ASP.NET Core RC2 MVC6 and IIS7 如何在ASP.NET Core中获取Active Directory当前用户显示名称? - How to get Active Directory current user Display Name in ASP.NET Core? ASP.NET 核心 MVC 身份 - 如何查看当前登录的用户? - ASP.NET Core MVC Identity - how to get current logged in user in view?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM