This week I have been working on a server control for a site I’m working on which reads in an XML file containing some product information and then using an XSL/T file transforms the output into correctly formatted XHTML. One problem which occurred with the development of the server control was that a colleague of mine who was making modifications to the XSL/T File was unable to save the changes whilst viewing the resultant XHTML in their browser. At first hand it would appear that it would be a permissions issue, and after much checking of the permissions to confirm they were correct, it was determined this was not the issue.
My colleague had been able to save changes to the XSL/T after a short while of the page processing which immediately pointed me to the fact that the object was still holding onto the resources. This was further confirmed with some investigation work which I did with the help of Craig Murphy.
The XMLReader object which was reading and transforming the XML using the XSL/T was still holding on to the file and placing a lock on it because the XMLReader object doesn’t have a dispose method and so therefore despite my setting the object to nothing, until the garbage collector picked up the objects then the lock on the XSL/T file remained. Craig suggested I call the XMLReader.Close() method after I had finished processing the XML, this was a method I wasn’t aware of and had not seen used in any example when I did my research into the changed syntax since version 2.0 of the .Net Framework.
Here is a code snippet below of an example of how to use the XMLReader.Close() method to release the locks on resources:
Dim strProductDataXML As String = "ProductData.xml" Dim strProductDataXSLT As String = "ProductDataTransform.xsl" Dim sb As New StringBuilder() Dim sw As New StringWriter(sb) ' Create XSL CompiledTransform to hold XSLT Dim objXSL As New XslCompiledTransform ' Create XsltSettings to hold XSLT Settings Dim objXSLTSettings As New XsltSettings(False, True) ' Create XmlReader Object to read the XSLT Dim objXSLReader As XmlReader ' Create XMLReaderSettings Object For XMLReader Object which will read the XSLT Dim objXSLReaderSettings As New XmlReaderSettings() ' Create XMLSecureResolver for use with the XSLCompiledTransform Dim objXMLResolver As New XmlSecureResolver(New XmlUrlResolver(), "http://www.mysite.com/") 'Create Reader Object to read the XSL Transform objXSLReader = XmlReader.Create(HttpContext.Current.Server.MapPath("~/XSLT/ProductDataTransform.xsl"), objXSLReaderSettings) ' Load the Transform in the XSLCompiledTransform Object, Provide the settings and resolver objects objXSL.Load(objXSLReader, objXSLTSettings, objXMLResolver) ' Set the Source of the ProductData XML File to be transformed Dim xmlSource As New XmlTextReader(HttpContext.Current.Server.MapPath("~/XML/ProductData.xml")) Dim xPathDoc As New XPathDocument(xmlSource) ' Call the close method on the XMLTextReader to release all resources which is attached too. xmlSource.Close() ' Perform the Transformation and output it to a stringwriter object objXSL.Transform(xPathDoc, Nothing, sw) ' Call the close method on the XSLReader to release all resources which is attached too. objXSLReader.Close() ' Set all objects to Nothing to allow the Garbage Collector to remove them strProductDataXML = Nothing strProductDataXSLT = Nothing objXSL = Nothing objXSLTSettings = Nothing objXSLReader = Nothing objXSLReaderSettings = Nothing objXMLResolver = Nothing xmlSource = Nothing xPathDoc = Nothing ' Return the transformed string Return sb.ToString()
Now that the XMLReader is closed and has released all of the objects holding on to it, the XSL/T file can be edited and changed without having to wait for the Garbage Collector to remove the objects and release the locks.