Can I do output caching in pages that I can detect in code behind if Session["user"] is null or not, and cache the page for 5 minutes if it is not cached yet (output caching not expired) and and the Session["user"] == null.
I don't want to use custom output cache because it will also cache for log in users. This way only anonymous visitors will see a cached, page, and logged in users will get the non cached ones
I do this because some of my pages looks different when the user is logged in or not. I want crawlers and regular visitors to see the original page, not getting a private data from a user that triggered the caching by mistake.
How can I do this in code behind C#?
You should be able to create a custom OutputCacheProvider
.
In your global.asax:
public override string GetOutputCacheProviderName(HttpContext context)
{
bool isInSession = true; // Determine here.
if (isInSession)
{
return "CustomProvider";
}
// Or by page:
if (context.Request.Path.EndsWith("MyPage.aspx"))
{
return "SomeOtherProvider";
}
return base.GetOutputCacheProviderName(context);
}
Then create your provider:
public class SessionBasedCacheProvider : OutputCacheProvider
{
public override object Get(string key)
{
return null; // Do not cache.
}
public override object Add(string key, object entry, DateTime utcExpiry)
{
// Basically let it "fall through" since we don't want any caching.
return entry;
}
public override void Set(string key, object entry, DateTime utcExpiry)
{
// Basically let it "fall through" since we don't want any caching.
}
public override void Remove(string key)
{
// Basically let it "fall through" since we don't want any caching.
}
}
By returning null
from Set, you will not cache the items.
The key value that identifies the specified entry in the cache, or null if the specified entry is not in the cache.
And add your provider to the config:
<system.web>
<caching>
<outputCache defaultProvider="AspNetInternalProvider">
<providers>
<clear/>
<add name="CustomProvider" type="YourNamespace.SessionBasedCacheProvider, YourNamespace, Version=1.0.0.0, Culture=neutral"/>
</providers>
</outputCache>
</caching>
</web>
To enable it you should be able to use. Just set this to the top of the ASPX-page. Note the Location
attribute, depending on where you want it to cache.
<%@ OutputCache Duration="60" VaryByParam="None" Location="Server" %>
https://msdn.microsoft.com/en-us/library/hdxfb6cy(v=vs.85).aspx
https://msdn.microsoft.com/en-us/magazine/gg650661.aspx
Alternatively you can always use the same CacheProvider, and let it determine if the item should be cached or not.
public class CustomOutputCacheProvider : OutputCacheProvider
{
public override object Add(string key, object entry, DateTime utcExpiry)
{
// Determine if in session.
bool isInSession = true;
if (isInSession)
{
return null;
}
// Do the same custom caching as you did in your
// CustomMemoryCache object
var result = HttpContext.Current.Cache.Get(key);
if (result != null)
{
return result;
}
HttpContext.Current.Cache.Add(key, entry, null, utcExpiry,
System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
return entry;
}
public override object Get(string key)
{
return HttpContext.Current.Cache.Get(key);
}
public override void Remove(string key)
{
HttpContext.Current.Cache.Remove(key);
}
public override void Set(string key, object entry, DateTime utcExpiry)
{
HttpContext.Current.Cache.Add(key, entry, null, utcExpiry,
System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
}
}
Code from http://www.haneycodes.net/custom-output-caching-with-mvc3-and-net-4-0-done-right/
Note, I've not tested this with Session, but in theory it should work. But I suggest that you really test it before releasing it. Caching is always much harder than one might think... :(
UPDATE: Since Session isn't available you should be able to use a cookie instead.
protected void Session_Start(object sender, EventArgs e)
{
Response.Cookies.Add(new HttpCookie("SessionCookie", "some_value"));
}
public override string GetOutputCacheProviderName(HttpContext context)
{
bool isInSession = true; // Determine here.
if (context.Request.Cookies["SessionCookie"] != null)
{
// Use your CustomProvider
}
if (isInSession)
{
return "CustomProvider";
}
// Or by page:
if (context.Request.Path.EndsWith("MyPage.aspx"))
{
return "SomeOtherProvider";
}
return base.GetOutputCacheProviderName(context);
}
Just remember to delete the cookie, or handle it in some way.