Sunday, April 12, 2009

Sharing Resources among WSPs is Dangerous

Did you know that if you create two different SharePoint solution packages (WSPs) that both share assemblies or even images, that retracting the one of the solutions will remove the resource and break the other WSP(s)?

Let’s say you have a shared utility library that has some common SharePoint routines in it that gets installed in the GAC.  Ideally, you would want your clients to only install one solution package for this functionality.  So you build a workflow, for instance, that uses your utility assembly and install it and everything is OK.  The way you’d do that is to modify the manifest.xml so that the WSP includes your assembly, installs it into the GAC and makes the appropriate Safe Control entry, if necessary.  Your manifest.xml might look something like this:

<?xml version="1.0" encoding="utf-8"?>
<Solution SolutionId="8d231d46-e165-4e39-8c69-dfd0d1b1d0de" ResetWebServer="True"
xmlns="http://schemas.microsoft.com/sharepoint/"
>
<!--Feature Manifest files-->
<
FeatureManifests
>
<
FeatureManifest Location="SuperWebPart\feature.xml"
/>
</
FeatureManifests
>
<!--Assembly files
-->
<
Assemblies
>
<
Assembly Location="SuperWebPart.dll" DeploymentTarget="GlobalAssemblyCache"
>
<
SafeControls
>
<
SafeControl Assembly="SuperWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=de41bace3a102f2c"
Namespace="SuperWebPart" TypeName="*" Safe="True"
/>
</
SafeControls
>
</
Assembly
>
<
Assembly Location="MySuperUtilities.dll" DeploymentTarget="GlobalAssemblyCache"
>
<
SafeControls
>
<
SafeControl Assembly="MySuperUtilities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=21bf3856ad364e35"
Namespace="MySuperUtilities" TypeName="*" Safe="True"
/>
</
SafeControls
>
</
Assembly
>
</Assemblies
>
</
Solution>

You can see how the instructions above will place the utility library (MySuperUtilities.dll) in the GAC.


Next, you build another web part (or some other SharePoint thing: workflow, web page…) that needs to use the same utility library.  You also want clients to only have to install this one WSP.  It’s just simpler for them to have to install one WSP as opposed to multiple.  And this new web part may be installed on a farm that doesn’t have the first on installed.  So you, being a well-intentioned developer, make sure your manifest.xml includes the utility assembly.  Your second web part might look something like this:

<?xml version="1.0" encoding="utf-8"?>
<!--
Manifest created STSDEV utility at 2/10/2009 1:37:08 PM
-->
<
Solution SolutionId="83224d36-a135-4bb9-cd39-dfdfddddfb23" ResetWebServer="True"
xmlns="http://schemas.microsoft.com/sharepoint/"
>
<!--
Feature Manifest files
-->
<
FeatureManifests
>
<
FeatureManifest Location="SuperDuperWebPart\feature.xml"
/>
</
FeatureManifests
>
<!--Assembly files
-->
<
Assemblies
>
<
Assembly Location="SuperDuperWebPart.dll" DeploymentTarget="GlobalAssemblyCache"
>
<
SafeControls
>
<
SafeControl Assembly="SuperDuperWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b3adf5ce3a132f33"
Namespace="SuperDuperWebPart" TypeName="*" Safe="True"
/>
</
SafeControls
>
</
Assembly
>
<Assembly Location="MySuperUtilities.dll" DeploymentTarget="GlobalAssemblyCache"
>
<SafeControls>
<
SafeControl Assembly="MySuperUtilities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=21bf3856ad364e35"
Namespace="MySuperUtilities" TypeName="*" Safe="True"
/>
</
SafeControls
>
</
Assembly
>
</Assemblies>
</
Solution>

So you can see how your two web parts will each install (and retract) the utility assembly (MySuperUtilities.dll).  Nice.  What happens when you want to install both web part packages on the same server.  No problem.  They both install and both work great.


Ok.  What’s the catch?  There’s always a catch :)  So the client decides that they don’t use the first web part.  They’ve decided to completely stop using it and want to retract the package using central admin or STSADM.  Unfortunately, as soon as they do that MySuperUtilities.dll is removed from the GAC, along with all the other files for this package.  Then the second web part will obviously break.



Note:


When talking about web parts and some other SharePoint coding concepts, you do have the option to use CAS (Code Access Security), which allows you to drop your DLLs in the /bin folder of your web application.  Using the bin avoids the complication of shared assemblies that may be removed.  The scenario that I’m describing here deals with a more common approach and that is adding assemblies in the GAC.  There’s a much larger discussion on CAS verses GAC, which I won’t go into here.


So how do we solve this dilemma?  Unfortunately, we have to install those shared resources manually or through a separate WSP.  I recommend a separate WSP, because it will assist you in deployment/retraction across an entire farm of servers.  So this WSP exists only to install DLLs or other shared resources.  This whole issue is a complex one to solve, but one I hope the SharePoint team addresses at some point.  It sure would be nice that before SharePoint retracted something in a farm, it would look at a complete list of farm resources in use by other packages to see if it can be retracted.  All that information is “known” by SharePoint in the configuration database anyway.  Then maybe it would prompt/warn users about these shared resources.

No comments:

Post a Comment