Stsadm is highly extensible and Gary Lapointe is one of the guys who could tell you everything about it. In order to support the deployment and administration of SharePoint solutions, Gary has created more than 130 custom STSADM commands. One of them – setwebpartstate has recently took my attention. I kept getting errors while importing a subclassed Content Query Web Part (CQWP) – until now…
Back in August 2007 Gary Lapointe has noticed that STSADM lacks functionality he needed for his project. At the same time he figured out that STSADM can be easily extended with custom commands. That’s when he started to create and share with the SharePoint community his custom STSADM commands.
SharePoint lacks a mechanism for provisioning configuration and content in a structured and repeatable way
A bit earlier in the beginning of 2007 we have noticed something similar here at Imtech ICT Velocity. We noticed that SharePoint lacks a mechanism for provisioning configuration and content in a structured and repeatable way. Although we have chosen a slightly different approach than Gary, there is some common functionality in both tools among which the possibility of provisioning a Web Part to a page using a .webpart/.dwp file.
Just recently, when we started using the Content Query Web Part in our projects we noticed something odd: while all other web parts were deploying correctly, we kept getting exceptions while importing the subclassed Content Query Web Part. Using Gary’s setwebpartstate command I have confirmed that it wasn’t because of a bug in our code but something else.
Each time you try to import a subclassed Content Query Web Part using an STSADM command you will get the following exception:
Request for the permission of type 'Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=126.96.36.199, Culture=neutral, PublicKeyToken=71e9bce111e9429c' failed.
The above exception is being thrown only if the assembly containing your custom web parts is deployed to a Web Application. As soon as you put it in the GAC the issue goes away and the web part gets imported correctly.
This leaves us with a couple of possibilities:
- Deploy all assemblies containing web parts to the GAC
- Copy all assemblies containing web parts to the 12\bin directory where STSADM.EXE is so that it can resolve the type
- Copy STSADM.EXE to the Web Application’s bin directory alongside the assemblies so that STSADM can once again resolve the types correctly
First one can be quite a security issue and in some situations not even possible to do. There are many scenarios when you’re not allowed/able to deploy a custom assembly to the GAC.
Also two other solutions don’t seem to be the right thing. They resemble more a quick & dirty solution and I bet that they wouldn’t make the server admins happy. So what’s there left to help us?
Back to basics: .NET Configuration
Thinking about the possible solutions I stumbled upon the .NET Configuration Files. The first thing that I tried was providing additional paths for probing. Unfortunately the provided paths must be subdirectories of the application directory. I could copy all the assemblies to 12\bin\bin but I was looking for a better solution.
Another way of telling STSADM where to look for an assembly is by using the dependentAssembly element. There are however three requirements. First of all your assembly must be signed. I have tried various settings, but the assembly has been discovered properly only while being signed.
The other information you have to provide is the codeBase. Both version and href attributes are required and the href attribute must contain the full path to your assembly. The modified STSADM.EXE.config file can look like this:
The last thing you need to modify is the XML of the exported web part (.dwp or .webpart depending on the base class). By default, the type name consists of the full class name only. That’s because of the fact that the underlying assembly is stored in the bin directory of the Web Application.
In order to allow STSADM to discover your assembly, you have to provide the full, 5 part class name instead:
If you try to provision the same subclasses Content Query Web Part a nice “Operation completed successfully” message will appear on the screen.
If you’re provisioning web parts from multiple assemblies you will need to create a dependentAssembly element for each one of them.
Provisioning Content Query Web Parts is not always as straight-forward as we would like it to be. If you’re using structure and repeatable deployment in your projects, deploying subclassed CQWPs together with other configuration provides you some extra control about the deployment process. Using basic .NET Configuration it is possible not only to provision web parts which are stored in the GAC but those which are deployed to Web Applications as well.