-
Embedded resources in XSL files
-
If you ever worked with embedded resources you probably know the required steps for embedding resources:
- Setting the build action to “Embedded Resource” in the file properties.
- Adding a web resource attribute with the file (best practice is to add this line in the AssemblyInfo.cs file) the first parameter is the default project namespace + the filename and the second parameter is the mime-type:
[assembly: WebResource("Namespace.Filename.gif", "image/gif")]
The WebResource attribute has a third parameter PerformSubstitution we will use this parameter if the file we use as an embedded resource (i.e. JavaScript, CSS, etc.) contain links to other embedded resources.
Here is an example of a URL to an embedded resources in a CSS file which is also an embedded resource:
.Classname
{
background-image:url('<% =WebResource("Namespace.Image.jpg") %>');
background-repeat:no-repeat;
background-position:left; height:25px;
}
In runtime this is rendered to:
.Classname
{
background-image: url('WebResource.axd?d=BAzWlMC4u9l74AvfGT40aSGC_Uhb-Uv5LVuAnHIqvgzwohb4KNp3sNEplurqJHjiqPl73PP2CdE4QL5GUaYRCA2&t=633818747586323927');
background-repeat:no-repeat;
background-position:left;
height:25px;
}
note that the URL was replaced by a WebResource.axd with two parameters: d is build from the following parameters “asseblyname|resourcename“ encoded using the Page.EncryptString and the t parameter is the timestamp of the assembly build (used for tracking changes).
So for everything look fine, the problem occurs when you try to use the
<%=WebResource(“…”)%> tag in an XML file (for example XSL) because the URL generated contains ampersand (&) the XML file is invalid for reading. (note the &t in the example above).
I thought there was a possibility to encode this string, but after digging using a reflector I found out that there is a function named: System.Web.Handlers.AssemblyResourceLoader.GetWebResourceUrlInternal this function looks (using RegEx) for the text <%=WebResource(“…”)%> and makes the replacement using the function: System.Web.Handlers.AssemblyResourceLoader.FormatWebResourceUrl(String, String, Int64, Boolean), the last parameter determines whether to encode the string or not, the main problem is that the HTTP handler which handles the web resources requests (System.Web.Handlers.AssemblyResourceLoader.System.Web.IHttpHandler.ProcessRequest) is calling the function with the desired parameter equals to false…
So I had to find a workaround because I had to load my XSL in JavaScript for performing the transform in client side, and when I used the load method of Msxml2.FreeThreadedDOMDocument it ended in an empty document because of the & problem. Here is my solution:
xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
xslDoc.async = false;
//Download the XSL using XMLHttpRequest (the js file is also embedded resource//which has the property PerformSubstitution=True in the assembly: WebResource//attribute)
var xhr_object = new XMLHttpRequest;
xhr_object.open("GET", '<% =WebResource("NameSpace.StyleSheet.xsl") %>', false);
xhr_object.send(null);
//Create a temp string to include the XSL
var tempXsl = xhr_object.responseText;
//Perform the subtituion of the illegal &t in the WebResource.axd link
tempXsl = replaceAll(tempXsl , '&t', '&t')
//Load the valid XML
xslDoc.loadXML(xsl);
Ugly but working….
David