Frequently storage of data and invalidating of cache problem
<p>In one of our projects we came across an interesting problem where we had to store data frequently which invalidated our OutputCache and caused a slow site. The scenario was that all users should be able to store bookmarks, contacts and tools (pages with information) to the specific user’s profile page seamlessly.</p>
Our first solution was to store all changes and elements as Serializable classes in property long string on the profile page. This worked fine locally but when we tested it in our customer’s environment with about 1000 users this went very slowly indeed. The reason of course was that when a user deleted or added a new element the EPiServer’s OutputCache got invalid. And when a lot of users were doing this constantly the entire site almost never showed a cached page.
The solution was to use XForms! With some help getting started from Erik Nordins blog post (http://antecknat.se/blog/tag/episerver-46/ his examples are from 4.x but it worked fine on our CMS 5 site as well) we started using XForms and with that we could store, collect and delete all the information we wanted without invalidating the cache.
The code is rather simple. First we get the XForm based on property name and linked it with the page guid. In this case we actually delete the XForm data after reading it since we are going to update it and store it later. Of course if you want to just read the data you don’t have to delete it.
public void GetAndUpdateXFormData()
{
XForm form = GetForm(profilePage.PageGuid, propertyName);
XFormData form_data = form.CreateFormData();
form_data.PageGuid = profilePage.PageGuid;
form_data.ChannelOptions = ChannelOptions.Database;
IList<XFormData> data = form.GetPostedData();
string sentData = string.Empty;
foreach (XFormData formData in data)
{
sentData = formData.GetValue(propertyName);
formData.Delete();
}
//Do what you need to do with sentData here
//Send the updated data as string
form_data.SetValue(propertyName, sp);
form_data.Send();
}
We use the function GetForm to collect the XForm for the specific page. If the page don’t have one it is created.
public static XForm GetForm(Guid pageGuid, string formName)
{
XForm retval = null;
//Search from db for a form where name == FORM_NAME
foreach (XForm xForm in XFormFolder.GetForms())
{
if (xForm.FormName != formName)
continue;
retval = xForm;
break;
}
if (retval == null) //Form is not found, so let's create it.
{
retval = XForm.CreateInstance();
retval.FormName = formName;
retval.AllowMultiplePost = true;
retval.AllowAnonymousPost = true;
retval.Save();
}
retval.PageGuid = pageGuid;
return retval;
}
And that’s it! You can now store data on a specific page without invalidating the cache.