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
};
}
}
}
}
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).
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With