1
votes

I have an asp.net webforms SaaS application where multiple ecommerce websites are running. Each website has its own domain (abc.com, xyz.com etc.) and each website's content is fetched from the database based on the domain.

Now, in order to improve home page performance I am implementing Output Cache. Please note that the home page already contains multiple user controls (header, footer, top menu, user menu, mini cart, banners, home products etc.). All the user controls are eligible for Output Cache accept user menu (where logged in usernames are displayed, otherwise signup/login links) and mini cart (where no. of cart items are displayed and on click it shows the list of items in cart).

I added Output cache directive on each user control (that I want to be cached) with VaryByCustom to create separate cache for each domain.

<%@ OutputCache Duration="300" VaryByParam="*" VaryByCustom="Host" %>

As VaryByHeader is not an available option for UserControls, I added an override function in Global.asax to return current host.

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg == "Host")
    {
        return context.Request.Url.Host;
    }

    return String.Empty;
}

Till now, everything is working perfect. User controls are being cached for different domains (hosts) and are being expired on the specified time.

THE PROBLEM: I want to give an option in the admin panel to the website admin users to manually refresh cache of their websites. For that I created a page (refreshcache.aspx) in the frontend application, and simply open that url (for example: abc.com/refreshcache.aspx) when the admin users click the refresh cache button from the admin panel.

I researched a lot and tried multiple approaches to clear user controls cache but failed. The last thing that I implemented is the following code which I added in the home page aspx which creates an object of StaticPartialCachingControl and adds key dependency on user controls cache.

In Home.aspx, I added the following code which is called in Page_Load

protected void LoadControlsCache()
{
    CacheKey = "Host-" + Request.Url.Host;
    CacheKeyArray[0] = CacheKey;

    if (Cache[CacheKey] == null)
    {
        AddControlCache(header1);
        AddControlCache(footer1);
        AddControlCache(banner1);
        AddControlCache(products1);
    }
}

protected void AddControlCache(UserControl uc)
{
        StaticPartialCachingControl pcc = (StaticPartialCachingControl)uc.Parent;
        pcc.Dependency = new CacheDependency(null, CacheKeyArray);
        Cache.Insert(CacheKey, "value", null, DateTime.Now.AddSeconds(300), Cache.NoSlidingExpiration);
}

And to remove the cache for a particular host, I used Cache.Remove method with the host specific key.

In refreshcache.aspx I added the following code

protected void Page_Load(object sender, EventArgs e)
{
    Cache.Remove("Host-" + Request.Url.Host);
    Response.Redirect("/");
}

I am not sure what I am missing or doing wrong. Just want a way to clear usercontrols cache for a particular host (domain).

1

1 Answers

0
votes

Finally got the issue resolved by creating separate keys for all user controls, and adding dependency on user control object.

protected void LoadControlsCache()
{
    string CacheKey = Request.Url.Host;

    AddControlCache(header1, "header-" + CacheKey);
    AddControlCache(footer1, "footer-" + CacheKey);
    AddControlCache(banner1, "banner-" + CacheKey);
    AddControlCache(products1, "products-" + CacheKey);
}

protected void AddControlCache(UserControl uc, string CacheKey)
{
    if (Cache[CacheKey] == null && uc != null)
    {
        uc.Cache.Insert(CacheKey, 1);
        uc.CachePolicy.Dependency = new System.Web.Caching.CacheDependency(null, new string[] { CacheKey });
    }
}

Then to clear the cache, used Cache.Remove() with all the usercontrol keys.

protected void Page_Load(object sender, EventArgs e)
{
    string CacheKey = Request.Url.Host;
    
    Cache.Remove("header-" + CacheKey);
    Cache.Remove("footer-" + CacheKey);
    Cache.Remove("banner-" + CacheKey);
    Cache.Remove("products-" + CacheKey);
    
    Response.Redirect("/");
}

Hope it might help someone with a similar question!