Skip to content

Instantly share code, notes, and snippets.

@Stephen2
Last active December 16, 2015 18:08
Show Gist options
  • Save Stephen2/5475043 to your computer and use it in GitHub Desktop.
Save Stephen2/5475043 to your computer and use it in GitHub Desktop.
Sitefinity SimpleView cache buster!!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SitefinityWebApp.Websilk.Code {
public class CacheSubWrap {
public Type widgetType { get; set; }
public Dictionary<string, object> properties { get; set; }
public delegate string RenderMarkupDelegate(Dictionary<string, object> properties, Type widgetType);
private RenderMarkupDelegate renderMarkup;
public CacheSubWrap(Dictionary<string, object> properties, Type widgetType, RenderMarkupDelegate renderMarkup) {
this.widgetType = widgetType;
this.properties = properties;
this.renderMarkup = renderMarkup;
}
public void RegisterPostCacheCallBack(System.Web.HttpContext context) {
context.Response.WriteSubstitution(Render);
}
public string Render(System.Web.HttpContext context) {
return renderMarkup(properties, widgetType);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Telerik.Sitefinity.Web.UI;
using System.Web.UI;
using System.Reflection;
namespace SitefinityWebApp.Websilk.Code {
public abstract class SimpleViewNoCache : SimpleView {
public bool preventCacheSub { get; set; }
private static string GetWidgetOutput(Dictionary<string, object> properties, Type widgetType) {
//Prevent recursive cache substitution
properties["preventCacheSub"] = true;
return new ViewManager().RenderView(widgetType, properties);
}
protected override void RenderContents(HtmlTextWriter writer) {
if (preventCacheSub) {
base.RenderContents(writer);
} else {
var cacheSub = new CacheSubWrap(GetPublicProperties(), GetType(), GetWidgetOutput);
cacheSub.RegisterPostCacheCallBack(Context);
}
}
/* REF: http://stackoverflow.com/questions/824802/c-how-to-get-all-public-both-get-and-set-string-properties-of-a-type */
protected Dictionary<string, object> GetPublicProperties() {
var props = new Dictionary<string, object>();
PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in properties) {
// If not writable then cannot null it; if not readable then cannot check it's value
if (!p.CanWrite || !p.CanRead) { continue; }
MethodInfo mget = p.GetGetMethod(false);
MethodInfo mset = p.GetSetMethod(false);
// Get and set methods have to be public
if (mget == null) { continue; }
if (mset == null) { continue; }
// Add to dictionary
props.Add(p.Name, p.GetValue(this, null));
}
return props;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Reflection;
namespace SitefinityWebApp.Websilk.Code {
public abstract class UserControlNoCache : UserControl {
public bool preventCacheSub { get; set; }
private static string GetWidgetOutput(Dictionary<string, object> properties, Type widgetType) {
//Prevent recursive cache substitution
properties["preventCacheSub"] = true;
return new ViewManager().RenderView(widgetType, properties);
}
protected override void Render(HtmlTextWriter writer) {
if (preventCacheSub) {
base.Render(writer);
} else {
var cacheSub = new CacheSubWrap(GetPublicProperties(), GetType(), GetWidgetOutput);
cacheSub.RegisterPostCacheCallBack(Context);
}
}
/* REF: http://stackoverflow.com/questions/824802/c-how-to-get-all-public-both-get-and-set-string-properties-of-a-type */
protected Dictionary<string, object> GetPublicProperties() {
var props = new Dictionary<string, object>();
PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in properties) {
// If not writable then cannot null it; if not readable then cannot check it's value
if (!p.CanWrite || !p.CanRead) { continue; }
MethodInfo mget = p.GetGetMethod(false);
MethodInfo mset = p.GetSetMethod(false);
// Get and set methods have to be public
if (mget == null) { continue; }
if (mset == null) { continue; }
// Add to dictionary
props.Add(p.Name, p.GetValue(this, null));
}
return props;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.IO;
using System.ComponentModel;
using Telerik.Sitefinity.Modules.Pages;
using System.Web.UI.HtmlControls;
/* REF: http://stackoverflow.com/questions/3138192/how-to-use-asp-net-server-controls-inside-of-substitution-control */
namespace SitefinityWebApp.Websilk.Code {
public class ViewManager {
private PageForRenderingUserControl pageHolder;
public ViewManager() {
pageHolder = new PageForRenderingUserControl();
}
public string RenderView(Type widgetType, Dictionary<string, object> data) {
pageHolder.Controls.Clear();
//Instantiate by type
var viewControl = Activator.CreateInstance(widgetType);
if (data != null) {
Type viewControlType = viewControl.GetType();
var properties = TypeDescriptor.GetProperties(viewControl);
foreach (string x in data.Keys) {
if ((properties[x] != null)) {
properties[x].SetValue(viewControl, data[x]);
}
}
}
pageHolder.Controls.Add((Control)viewControl);
StringWriter result = new StringWriter();
try {
HttpContext.Current.Server.Execute(pageHolder, result, false);
} catch (Exception ex) {
result.WriteLine(ex.Message);
}
return result.ToString();
}
private class PageForRenderingUserControl : Page {
public override void VerifyRenderingInServerForm(Control control) {
// Do nothing
}
public override bool EnableEventValidation {
get { return false; }
// Do nothing
set { }
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment