使用 Ninject (ASP.NET MVC) 将会话变量注入 IService

Injecting a session variable into an IService using Ninject (ASP.NET MVC)

我有一个大小适中的 Web 应用程序,我想制作多客户端。所以现在我有一个用户 table,我的计划是向该 table 添加一个 ClientId 字段,然后我可以限制用户只能看到他们所属的客户端的数据。

在理想情况下,我想尝试将安全性设置在最低级别,这样就很难意外创建导致客户端看到另一个客户端数据的功能。因此,当我在控制器中使用服务时,不必每次都传递 clientId:

var messages = _messageService.GetMessagesByType(clientId, type);

它是自动的:

var messages = _messageService.GetMessagesByType(type);

我正在使用 Ninject 将我的服务注入控制器:

    public static void RegisterTypes(IKernel kernel)
    {
        kernel.Bind<IMessageService>().To<MessageService>();
    }

我目前的想法是将当前用户的 clientId 存储为会话变量,然后以某种方式将其注入 IServices,然后再在控制器中使用它们。

但是,我假设 RegisterTypes 方法在 App_Start 上被调用了一次,那么当一个动作被调用时我将如何注入它?还是有更好的方法来实现我想要实现的目标?

可悲的是,我对 web 开发和特别是 asp.net-mvc 知之甚少。但是,以下可能是您可以接受的解决方案: (注意:我假设客户端 ID 的类型为 ClientId。请参阅 here 了解原因。) 给定:

public class MessageService : IMessageService
{
    public MessageService(ClientId clientId,...) {...}

    ...
}

您可以定义绑定:

kernel.Bind<IMessageService>().To<MessageService>
      .WithParameter(new TypeMatchingConstructorArgument(
          typeof(ClientId),
          (ctx, target) => (ClientId)HttpContext.Current.Session["clientId"]));

HttpContext.Current.Session["clientId"] 的值注入 ClientId 类型的参数到 MessageService 的构造函数中。 除了 TypeMatchingConstructorArgument,您还可以使用 ConstructorArgument 参数,它按参数名称而不是参数类型进行匹配。

现在更进一步,它也适用于其他服务,我们也可以简单地做:

kernel.Bind<ClientId>()
      .ToMethod(ctx => ClientId)HttpContext.Current.Session["clientId"]);

kernel.Bind<IMessageService>().To<MessageService>();

注意:您可能需要考虑添加(到绑定)验证是否存在会话以及是否设置了 clientId。

另请注意:在实例化服务(= 由控制器或其依赖项之一请求)之前,您需要注意 clientId 实际上是已知的(放在会话中)。