Over the past few months, I've had the opportunity to code review several different private and commercial products built on SharePoint.
One of the things that I noticed is that folks are putting Web Part related files (css, js, images, ascx) all over the place...
Naturally, I have to ask why... often times, folks just dump files into the locations that seemingly make sense... for example, images often times go in "layouts/images" or any number of other layouts locations, user controls get dumped into controltemplates, sometimes they are embedded into the web part assembly, sometime they are pushed into doc libs, etc...
Reasonable logic but when I ask why the web part resources folder wasn't used, some folks stop and ask "what is that?"
So, it seems that web part resources have somewhat fallen off the radar...
What are Web Part resources? Each Web Part assembly has an opportunity to associate any number of files with itself. This is defined in the Solution file via the
ClassResource element.
The files will be deployed to one of two locations, depending on your installation type (GAC or bin). The locations are nothing more than virtual directories that live on the web front ends. The bin version (/wpresources) does not allow certain types of files to be rendered (.asax, .ascx, .ashx, .asmx, .aspx). The GAC version (/_wpresources) is not as restrictive and pretty much available to host all page types.
Why is it good to put resources such as js, css, images, ascx files in the Web Part resources folder?
- You automatically get our own storage location. SharePoint creates a unique folder for your assembly.
- Since it's on the file system, you get the inherent benefits of not hitting the database and automatically utilizing IIS for managing file caching and/or compression (for those instance where related files are put into sharepoint itself)
- You don't even have to worry about the path... SharePoint gives that you.
The path is retrieved using the static method GetServerRelativeClassResourcePath that hangs off the SPWebPartManager class.
Throw your images, css, .ascx files, and whatever else you need in there!
Wait... .ascx files? Don't user controls have to go into ControlTemplates? Don't they have to be registered in the SafeControls list?
The answer depends on how you call the ascx files. A lot of folks use .ascx files as templates for their Web Parts (meaning they have a shell Web Part that calls Page.LoadControl to load their ascx file). If your Web Part directly loads the user control, then using class resources is perfectly viable opportunity. The SafeControls list is only applied to controls that are explicitly created via page markup. The key point to remember here is that your Web Part is SafeControl-approved because it was explicitly created and parsed as part of the page; however once the code is running, it can do anything it wants (as allowed by the CAS policy) . Thus, loading a file off the system is perfectly valid and not routed through the SafeControls monitor.
On the other hand, if you are deploying ascx files as standalone controls then your best best continues to be controltemplates (given the location and the SafeControl entry exists). The hard limitation here is the fact that the bin-version of wpresources does not allow .ascx files to be rendered directly (in other words, even if you had the right SafeControls entry, iis would prohibit the control from being rendered).
The next time you deploy a Web Part that has some support files, don't forget to look at ClassResources before putting files elsewhere.
-Maurice