Make MVC Sitemap unique per session, not user

这一生的挚爱 提交于 2019-12-02 09:35:32
NightOwl888

Option 1:

Implement your own ICacheProvider based on session state and inject it using DI.

using System;
using System.Collections.Generic;
using MvcSiteMapProvider.Web.Mvc;
using MvcSiteMapProvider.Caching;
using System.Web;

public class SessionStateCacheProvider<T>
    : ICacheProvider<T>
{
    public SessionStateCacheProvider(
        IMvcContextFactory mvcContextFactory
        )
    {
        if (mvcContextFactory == null)
            throw new ArgumentNullException("mvcContextFactory");
        this.mvcContextFactory = mvcContextFactory;
    }
    private readonly IMvcContextFactory mvcContextFactory;

    protected HttpContextBase Context
    {
        get
        {
            return this.mvcContextFactory.CreateHttpContext();
        }
    }

    #region ICacheProvider<ISiteMap> Members

    public bool Contains(string key)
    {
        return (Context.Session[key] != null);
    }

    public Caching.LazyLock Get(string key)
    {
        return (LazyLock)Context.Session[key];
    }

    public bool TryGetValue(string key, out Caching.LazyLock value)
    {
        value = this.Get(key);
        if (value != null)
        {
            return true;
        }
        return false;
    }

    public void Add(string key, LazyLock item, ICacheDetails cacheDetails)
    {
        // NOTE: cacheDetails is normally used to set the timeout - you might
        // need to roll your own method for doing that.
        Context.Session[key] = item;
    }

    public void Remove(string key)
    {
        Context.Session.Remove(key);
    }

    public event EventHandler<MicroCacheItemRemovedEventArgs<T>> ItemRemoved;

    #endregion

    // NOTE: Normally this is called by a callback from the cache when an item exprires.
    // It is required to ensure there is no memory leak because a sitemap has circular references
    // that need to be broken explicitly. You need to work out how to call this when the user's session
    // expires.
    protected virtual void OnCacheItemRemoved(MicroCacheItemRemovedEventArgs<T> e)
    {
        if (this.ItemRemoved != null)
        {
            ItemRemoved(this, e);
        }
    }

}

Then inject it like this (StructureMap example shown):

// Setup cache
SmartInstance<CacheDetails> cacheDetails;

this.For<ICacheProvider<ISiteMap>>().Use<SessionStateCacheProvider<ISiteMap>>();

var cacheDependency =
    this.For<ICacheDependency>().Use<NullCacheDependency>();

cacheDetails =
    this.For<ICacheDetails>().Use<CacheDetails>()
        .Ctor<TimeSpan>("absoluteCacheExpiration").Is(absoluteCacheExpiration)
        .Ctor<TimeSpan>("slidingCacheExpiration").Is(TimeSpan.MinValue)
        .Ctor<ICacheDependency>().Is(cacheDependency);

Option 2:

Append the user name to the siteMapCacheKey in a custom ISiteMapCacheKeyGenerator, and inject it via DI:

public class SessionBasedSiteMapCacheKeyGenerator
    : ISiteMapCacheKeyGenerator
{
    public UserBasedSiteMapCacheKeyGenerator(
        IMvcContextFactory mvcContextFactory
        )
    {
        if (mvcContextFactory == null)
            throw new ArgumentNullException("mvcContextFactory");
        this.mvcContextFactory = mvcContextFactory;
    }

    protected readonly IMvcContextFactory mvcContextFactory;

    #region ISiteMapCacheKeyGenerator Members

    public virtual string GenerateKey()
    {
        var context = mvcContextFactory.CreateHttpContext();
        var builder = new StringBuilder();
        builder.Append("sitemap://");
        builder.Append(context.Request.Url.DnsSafeHost);
        builder.Append("/?sessionId=");
        builder.Append(context.Session.SessionID);
        return builder.ToString();
    }

    #endregion
}

Inject it like this (StructureMap example):

this.For<ISiteMapCacheKeyGenerator>().Use<SessionBasedSiteMapCacheKeyGenerator>();

Note that using an external DI container is required.

Please see my open question here and explain to me why you would want to do this on GitHub, as it renders most of the features useless: https://github.com/maartenba/MvcSiteMapProvider/issues/16#issuecomment-22229604

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!