MVC3中的Ninject会话范围概念

时间:2012-05-04 08:20:34

标签: c# asp.net-mvc ninject

我正在使用Ninject框架构建MVC3应用程序。我有一个耗时的服务初始化,最后这个服务将有一个包含用户特定信息的对象,然后我需要重新使用该服务,只要用户会话是活动的,这样我可以避免一次又一次地初始化该服务

所以我的问题是

当我使用Ninject绑定服务时,我应该选择哪种范围,Ninject中的每个范围都没有会话,那么实现该要求的最佳方法是什么?还是我走错了方向?

我为我的一个服务创建了一个自定义提供程序,它将根据从当前Controller.User.Identity.Name中获取的用户名详细信息创建服务。下面的代码不起作用,因为缺少userName局部变量,如何通过Ninject将用户名值传递给我的自定义提供程序,以便我可以从IContext中提取它?

public class TfsConnectionManagerProvider : Provider<TfsConnectionManager>
    {
        protected override TfsConnectionManager CreateInstance(IContext context)
        {
            Uri serverUri = new Uri(ConfigurationHelper.TfsServerUrl);
            // Connect to the server without impersonation
            using (TfsTeamProjectCollection baseUserConnection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(serverUri))
            {
                // Get the identity management service
                IIdentityManagementService ims = baseUserConnection.GetService<IIdentityManagementService>();

                // Get the identity to impersonate
                TeamFoundationIdentity identity = ims.ReadIdentity
                (
                    IdentitySearchFactor.AccountName,
                    userName,  //NOTE: How can I get user name value from IContext???
                    MembershipQuery.None,
                    ReadIdentityOptions.None
                );

                // Connect using the impersonated identity
                using (TfsTeamProjectCollection impersonatedConnection = new TfsTeamProjectCollection(serverUri, identity.Descriptor))
                {
                    WorkItemStore store = impersonatedConnection.GetService<WorkItemStore>();

                    return new TfsConnectionManager
                    {
                        Store = store
                    };
                }
            }
        }
    }

3 个答案:

答案 0 :(得分:7)

Ninject故意不提供会话范围,因为在几乎所有情况下,会话状态中的服务都是错误的。你应该非常谨慎地使用会话状态,因为它带来了许多缺点。

尝试首先使用无状态应用程序。

如果有足够的理由在会话范围内拥有数据,那么将该数据(而不是服务)放入会话状态,并使用单例,瞬态或请求范围内的服务进行处理(数据和功能的分离)

答案 1 :(得分:2)

我最终使用自定义Provider来创建实例,并在自定义提供程序中检查它是否存在于会话中。

绑定完成如下

Bind<IRepository>().ToProvider(new TfsRepositoryProvider());

自定义提供商位于

之下
public class TfsRepositoryProvider : Provider<TfsRepository>
    {
        private const string SesTfsRepository = "SES_TFS_REPOSITORY";

        protected override TfsRepository CreateInstance(IContext context)
        {
            // Retrieve services from kernel
            HttpContextBase httpContext = context.Kernel.Get<HttpContextBase>();

            if (httpContext == null || httpContext.Session == null)
            {
                throw new Exception("No bind service found in Kernel for HttpContextBase");
            }

            return (httpContext.Session[SesTfsRepository] ?? (
                    httpContext.Session[SesTfsRepository] = new TfsRepository(context.Kernel.Get<IWorkItemStoreWrapper>()))
                ) as TfsRepository;
        }
    }

答案 2 :(得分:0)

好的,您可以在应用程序中缓存/存储用户信息,如果您没有(最近的)用户信息,则只能调用外部服务。在您的用户信息检索“层”中,您只需编写这两种可能性。

你缓存的地方,完全取决于你。您可以将此信息存储在本地数据库中。

显然我理解你错了,道歉(低于我原来的答案)。

  

您可以使用例如包含静态的(抽象)工厂   您的服务成员(例如),因此它将被重用。

     

虽然取决于您的服务,但这可能会有一些不必要的方面   效果(我曾经使用Data Services和ASP.NET MVC3做过一次   应用程序我的数据上下文因为一些魔法而有点紧张   发生过)。我想说的就是:小心并测试它   好。