0

Ninject doesn’t provide a InSessionScope Binding for Websites, so we have created our own extension:

public static IBindingNamedWithOrOnSyntax<T> InSessionScope<T>(this IBindingInSyntax<T> parent)
{
   return parent.InScope(SessionScopeCallback);
}

private const string _sessionKey = "Ninject Session Scope Sync Root";

private static object SessionScopeCallback(IContext context)
{
    if (HttpContext.Current.Session[_sessionKey] == null)
    {
        HttpContext.Current.Session[_sessionKey] = new object();
    }
    return HttpContext.Current.Session[_sessionKey];
}

This extension is working fine until we are using the standard local SessionStore.

But we changed the SessionStore and we now use the „AppFabricCacheSessionStoreProvider“ and this store is no longer on the local machine its on the server.

And the problem is that Ninject tries to resolve the reference of an object which was serialized and deserialized and comes from the server and not from the local memory and so ninject can’t find the reference. The result is, that ninjects allways creates a new Object and the SessionScope does not work any more.

Edit 1:

We are using this functionality

https://msdn.microsoft.com/en-us/library/hh361711%28v=azure.10%29.aspx

and here I can use the standard "HttpContext.Current.Session" Object and the list content is stored on the server and not on the local machine.

squadwuschel
  • 3,328
  • 3
  • 34
  • 45
  • Can you add the code for app fabric? – zaitsman Feb 25 '15 at 09:21
  • there is no code for the AppFabric - its only a setting in the web.config and then all SessionData is stored on a server and no more in the local machine. I need to rewrite the InSessionScope extension somehow but I don't know how – squadwuschel Feb 25 '15 at 09:36
  • well that is exactly my question, what was the code in your extension. Because no matter what you wired in web.config, HttpContext.Current will not return you the AppFabric cache. Anyways, which version of AppFabric do you have? (1.0 or 1.1) – zaitsman Feb 25 '15 at 09:43
  • AppFabric Cache Version 1.1 – squadwuschel Feb 25 '15 at 10:06
  • The link you added doesnt say that you can use 'HttpContext.Current.Session'? – zaitsman Feb 25 '15 at 10:32
  • When you implement the AppFabric like shown in the link you can use "HttpContext.Current.Session" like in my example it works fine so far. – squadwuschel Feb 25 '15 at 12:28

2 Answers2

0

So architecturally you have a problem in that you need to store the settings for AppFabric somewhere, and this is an issue with your static method. But assume you create a public static class like so:

public static class AppCache
{

    public static DataCache Cache { get; private set; }

    static AppCache()
    {
        List<DataCacheServerEndpoint> servers = new List<DataCacheServerEndpoint>(1);

        servers.Add(new DataCacheServerEndpoint("ServerName", 22233)); //22233 is the default port

        DataCacheFactoryConfiguration configuration = new DataCacheFactoryConfiguration
        {
            Servers = servers,
            LocalCacheProperties = new DataCacheLocalCacheProperties(),
            SecurityProperties = new DataCacheSecurity(),
            RequestTimeout = new TimeSpan(0, 0, 300),
            MaxConnectionsToServer = 10,
            ChannelOpenTimeout = new TimeSpan(0, 0, 300),
            TransportProperties = new DataCacheTransportProperties() { MaxBufferSize = int.MaxValue, MaxBufferPoolSize = long.MaxValue }
        };

        DataCacheClientLogManager.ChangeLogLevel(System.Diagnostics.TraceLevel.Off);

        var _factory = new DataCacheFactory(configuration);

        Cache = _factory.GetCache("MyCache");
    }
}

then you can change extension like so:

public static IBindingNamedWithOrOnSyntax<T> InSessionScope<T>(this IBindingInSyntax<T> parent)
{
   return parent.InScope(SessionScopeCallback);
}

private const string _sessionKey = "Ninject Session Scope Sync Root";

private static object SessionScopeCallback(IContext context)
{
    var cachedItem = AppCache.Cache.Get("MyItem"); // IMPORTANT: For concurrency reason, get the whole item down to method scope.
    if (cachedItem  == null)
    {
        cachedItem = new object();
        AppCache.Cache.Put("MyItem", cachedItem);
    }
    return cachedItem;
}
zaitsman
  • 8,984
  • 6
  • 47
  • 79
  • The App Fabric Cache works like a charm with my implementation above, thats not the Problem. Our Problem is that the Ninject InSessionScope does not work with the AppFabric cache because ninjects works with local references and when I use the AppFabric cache there is no local reference any more and I allways get a new object instanciated from ninject – squadwuschel Feb 25 '15 at 10:55
  • Well appfabric wont give you a local reference, each object is deserialized everytime. E.g. you can't use it like that. – zaitsman Feb 25 '15 at 10:58
0

I've found a "Solution" that works so far it's not perfect because I am avoiding the AppFabric Store with an Localstore for the Object Reference.

    public static IBindingNamedWithOrOnSyntax<T> InSessionScope<T>(this IBindingInSyntax<T> parent)
    {
       return parent.InScope(SessionScopeCallback);
    }

    public static Dictionary<string, object> LocalSessionStore = new Dictionary<string, object>();

    private const string _sessionKey = "Ninject Session Scope Sync Root";

    private static object SessionScopeCallback(IContext context)
    {
        var obj = new object();
        var key = (string)HttpContext.Current.Session[_sessionKey];

        if (string.IsNullOrEmpty(key))
        {
            var guid = Guid.NewGuid().ToString();
            HttpContext.Current.Session[_sessionKey] = guid;
            LocalSessionStore.Add(guid, obj);
        }
        else if(!LocalSessionStore.ContainsKey(key))
        {
            LocalSessionStore.Add(key, obj);
            return LocalSessionStore[key];
        }
        else if (LocalSessionStore.ContainsKey(key))
        {
            return LocalSessionStore[key];
        }

        return HttpContext.Current.Session[_sessionKey];
    }
}
squadwuschel
  • 3,328
  • 3
  • 34
  • 45