【问题标题】:How to handle session information in an Asp.net MVC app with dependency injection如何使用依赖注入处理 Asp.net MVC 应用程序中的会话信息
【发布时间】:2015-04-24 02:58:32
【问题描述】:

我有一个多租户应用程序,我想跟踪整个应用程序中的两件事:用户和租户。

我有这三种情况:

  1. 匿名用户:在这种情况下,user 为空,tenant 由查询字符串跟踪。
  2. Authenticated Users:user来自cookie,tenant保存在session中。
  3. 作业:我的应用中有作业要做,在这种情况下,user 为 null,tenant 是手动设置的。

在我的所有服务中,我都使用用户和租户。

一开始我坚持在我的 DI 容器中为每个 http 会话使用一个对象,但这不适用于 Jobs。

关于如何处理这些信息的任何问题,我目前在 Session 变量中使用它,但是我在这个实现中有很多问题,我需要有很多特殊情况来处理作业和未经身份验证的用户。

【问题讨论】:

  • 您使用的是 DI 库吗?如果有,是哪一个?
  • 我现在没有使用任何东西,但我想使用 Simple Injector
  • 让租户成为路由的第一段,然后是控制器和操作。这非常灵活,应该可以解决您的所有问题。

标签: asp.net asp.net-mvc session dependency-injection


【解决方案1】:

您至少应该抽象对用户上下文的访问。例如:

public interface IUserContext {
    IPrincipal User { get; }
    Tenant Tenant { get; }
}

您可能希望有一个单独的 ITenantContext 抽象,但现在让我们坚持一个。

您的系统可能有两个应用程序:运行作业的 Windows 服务和处理用户交互的 Web 应用程序。这两个应用程序都有自己的入口点、自己的 Composition Root 和自己独特的 DI 配置。

对于 Web 应用程序,我想实现如下所示:

public AspNetUserContext : IUserContext
{
    private readonly ITenantRepository tenantRepository;

    public AspNetUserContext(ITenantRepository tenantRepository) {
        this.tenantRepository = tenantRepository;
    }

    public IPrincipal User {
        get { return HttpContext.Current.User; }
    }

    public Tenant Tenant {
        get { 
            if (this.User.Identity.IsAuthenticated) {
                return this.tenantRepository.GetByName(
                    HttpContext.Current.Session["tenant"]);
            } else {
                return this.tenantRepository.GetByName(
                    HttpContext.Current.Request.QueryString["tenant"]);
            }
        }
    }
}

对于作业服务,一开始可能看起来完全不同,但是对于服务,处理一个作业可以被视为一个请求。这意味着当请求开始时,您需要设置上下文(ASP.NET 在后台为我们所做的事情)。 IUserContext 可能如下所示:

public JobServiceUserContext : IUserContext
{
    [ThreadStatic]
    private static IPrinciple user;

    [ThreadStatic]
    private static Tenant tenant;

    public IPrincipal User { 
        get { return this.user; }
        set { this.user = user; }
    }

    public IPrincipal User { 
        get { return this.tenant; }
        set { this.tenant = tenant; }
    }
}

现在可以使用一些设置适当上下文的逻辑来包装作业的执行,例如:

public class JobRunner {
    private readonly JobServiceUserContext context;
    private readonly IJobDactory jobFactory;
    public JobServiceUserContext(JobServiceUserContext context,
        IJobDactory jobFactory) {
        this.context = context;
        this.jobFactory = jobFactory;
    }

    public void RunJob(JobDetails job) {
        try {
            this.context.User = job.User;
            this.context.Tenant = job.Tenant;

            IJob job = this.jobFactory.Create(job.Type);

            job.Execute(job.Data);

            Activator.CreateInsta
        } finally {
            // Reset
            this.context.Tenant = null;
            this.context.User = null;
        }
    }
}

更新

如果它们都在同一个应用程序中运行,并且作业在后台线程上运行,您可以为IUserContext 引入代理实现,透明地切换到正确的实现。例如:

public SelectingUserContextProxy : IUserContext {
    private readonly Func<bool> selector;
    private readonly IUserContext trueContext;
    private readonly IUserContext falseContext;
    public SelectingUserContextProxy(Func<bool> selector,
        IUserContext trueContext, IUserContext falseContext) {
        this.selector = selector;
        this.trueContext = trueContext;
        this.falseContext = falseContext;
    }

    public IPrincipal User { get { return this.Context.User; } }
    public Tenant Tenant { get { return this.Context.Tenant; } }

    private IUserContext Context {
        get { return selector() ? trueContext : falseContext; }
    }
}

您可以按如下方式注册:

var jobContext = new JobServiceUserContext();

container.RegisterSingle<IUserContext>(
    new SelectingUserContextProxy(
        () => HttpContext.Current != null,
        trueContext: new AspNetUserContext(),
        falseContext: jobContext));

【讨论】:

  • 如果我的工作在同一个应用程序中怎么办?我正在使用 Quartz.net 来安排作业。我应该如何配置 DI?
猜你喜欢
  • 1970-01-01
  • 2014-10-11
  • 2022-11-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 2017-11-13
  • 1970-01-01
相关资源
最近更新 更多