Working with BlogEngine.NET allows everyone the luxury of creating useful extensions and controls that help improve functionality and features. One thing I have noticed is that it's pretty much up to each person to understand how to implement the code that's included in the extension. Often times this is something as simple as reading/writing an XML file.
A problem I have run into on several occasions has to deal with the various XML files that BlogEngine.NET uses. For example, I was trying to create my subscription list XML file and then refresh the Gridview contents. I kept wrestling with the fact that changes to the XML file was in cache and didn't immediately show up in the GridView results. I also noticed that when I was using the Toolbox extension that I couldn't make any manual changes to the XML document while my blog was running because the changes would be overwritten sometime in the near future. Very annoying, so I started looking into what I can do about this issue.
I didn't have to look very far, as handling files in BlogEngine pretty much use the same mechanism. It usually starts with a global declaration of _Document and then somewhere in the extension the function would look to see if the _Document was null. If it was null then the GetXMLDocument function was called to load the XML document:
XmlDocument _Document;
private static XmlDocument GetXMLDocument(string xmlFileName)
{
try
{
_Document = new XmlDocument();
if (!File.Exists(xmlFileName))
{ BuildXMLDocument(xmlFileName); }
_Document.Load(xmlFileName);
return _Document;
}
catch { return null; }
}
No problem here, as the result is the XML file is loaded, except that _Document is now loaded for the life of the application. No checking for external modifications of the XML file is being performed. In fact, modifications to the source file will be overwritten the next time the _Document is given the .Save command. Ouch. I've been bitten by this feature many times.
After looking around I believe I have found a better way to handle XML files and I wanted to share this with everyone...
The goal is to cache the contents of the XML file in order to minimize the cost of disk reads, but ensure that the XML file is reloaded whenever there are external changes to the document. Lets look at the CacheDependency feature of HTTP Cache. CacheDependency forces the application to clear the cache whenever the dependency file has been modified. So what would the GetXMLDocument look like if I used HTTP Cache and the CacheDependency? Have a look:
private static XmlDocument GetXMLDocument(string xmlFileName)
{
// Check if xmlFileName is in cache
XmlDocument _Document = (XmlDocument)HttpRuntime.Cache[xmlFileName];
if (_Document == null)
{
try
{
_Document = new XmlDocument();
if (!File.Exists(xmlFileName))
BuildXMLDocument(xmlFileName);
_Document.Load(xmlFileName);
// Load into cache for future use
//HttpContext.Current.Cache.Insert(xmlFileName, _Document, new CacheDependency(xmlFileName));
HttpRuntime.Cache.Insert(xmlFileName, _Document, new CacheDependency(xmlFileName));
}
catch (FileNotFoundException)
{
// Document wasn't found
_Document = null;
}
}
return _Document;
}
A little more code but in my opinion the results are well worth it.
<rant> I am not really a developer, I just play one on the Internet... So when I ran across an exhaustive discussion about whether to use HTTP.Runtime.Cache instead of HTTP.Context.Cache I quickly became bored and moved on to greener pastures. If you care about this topic then I would encourage you to look into it yourself and let me know what you discover. In the meantime I went with HTTP.Runtime.Cache </rant>
Now, you might not want to use HTTP Cache for really large XML files, but for extension files storing small amounts of data it works perfectly. I have been updating most of my code to use this method without any adverse effects. What do you think? Is this something that works for you? Do you see anything wrong with using this function?