Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject session scope concept in MVC3

I am building a MVC3 app using Ninject framework. I have a service that is time-consuming to initialize, and at the end this service will has an object that contains user-specific information, then I need to re-use that service as long as the user session is active, so that I can avoid to initialize that service again and again

So my question is

When I bind the service using Ninject what kind of scope should I pick, there is no session per scope in Ninject, so what is the best way to implement the requirement? or did I went to a wrong direction at all?

I've created a custom provider for one of my services that will create the service based on username details that is grabbed from current Controller.User.Identity.Name. The code below won't work because the userName local variable is missing, how can I pass the user name value into my custom provider via Ninject, so that I can pick it up from 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
                    };
                }
            }
        }
    }
like image 439
Ming Avatar asked May 04 '12 08:05

Ming


2 Answers

A session scope is intentionally not offered in Ninject, because having services in a session state is wrong in almost every situation. You should be very carefully about using session state because it brings a lot of disadvantages.

Try to have a stateless application in first place.

If there is a good reason for having data in session scope then put that data (not the services) into the session state and use services that are in singleton, transient or request scope for the processing (separation of data and functionality).

like image 60
Remo Gloor Avatar answered Oct 08 '22 06:10

Remo Gloor


I turn out to use custom Provider for creating the instance and in the custom provider I checked if it exists in session or not.

The binding is done as following

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

The custom Provider is below

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;
        }
    }
like image 22
Ming Avatar answered Oct 08 '22 04:10

Ming