Saturday, 12 May 2007

Deploying web parts as a feature

This time we're talking about how to deploy web parts as a feature. Now, deploying custom web parts the manual way is a bit of a pain - the following things are required for the web part to be used:-

  • the assembly containing the compiled web part class to be in the GAC (or site bin with appropriate CAS policy)
  • a SafeControls entry in the site web.config to tell SharePoint this control is administrator-approved
  • the .webpart (or .dwp) file which contains the web part definition (configuration) to be uploaded to the site's web part gallery

Assuming the user has appropriate permissions, the web part can then be added to a WebPartZone on a web part page. The first thing to say is that there are 2 ways of automating this process:-

  • use VSeWSS to create a feature to deploy the web part - simply hit F5 to deploy to your local server; this also generates a SharePoint solution package (.wsp) which can be deployed to other environments.
  • create a feature 'manually' by creating the files (e.g. feature.xml, elements file etc.) by hand

Both methods will take care of the 3 steps listed above, so that the files are copied and the SafeControls entry is added. I can't emphasise enough how simple VseWSS makes this process. Additionally, VSeWSS apparently allows simple debugging when F5 is hit, but I had to copy the .pdb file to the hidden folders in the GAC hierarchy to enable this. See my article on how to debug feature receivers for more information.

However, use of VSeWSS typically means there is slightly less control over the deployment options, since the tool writes the files for you and not all of the options are exposed for you to modify (I go into more detail on this in Creating lists with VSeWSS). As an example, VSeWSS will deploy web part assemblies to the GAC (with full trust), but some SharePoint admins prefer assemblies to run from private bin folders instead to isolate any harm they might do. Hence, there are some occasions where you might want to use the second option and create the feature yourself. The remainder of this article illustrates this process, using the example of a web part which should be deployed to a bin folder.

Once the webpart has been developed, we need to create the manifest file, specifying the feature details, assembly, SafeControls entry, and webpart definition file (.webpart):-


Then, we need the feature.xml file which points to the elements file and tells the framework there is another file to process (that being the .webpart file):-



The elements.xml file should look something like:-



Finally, a .webpart file should be generated to define the metadata and default property values of the webpart.




I place this in a folder underneath my feature files alongside the .dll file containing the compiled assembly.

Assuming all the files are in the right place, the solution file (.wsp) can be built using makecab.exe. This solution can now be deployed, thus taking care of the manual steps for webpart deployment. Once this process is familiar (and you have existing files to copy for the next time) this process is quite straightforward.

[UPDATE 22 November 2007 : for bin deployments, the .dll should be at the root of the .wsp file - if it is in a subfolder, it will be deployed to a subfolder of the bin directory which we do not want. See this article's comments for more details.]

Note the DeploymentTarget="WebApplication" instruction in the manifest.xml file. This ensures the assembly is deployed to the application bin folder rather than the GAC. Now, most web parts will require additional CAS policy to obtain the permissions to execute - your assembly will now have the default trust level of WSS_Minimal, so any file io, database or web service access will probably fail. I hope to cover the entries for this in a future article.

So the webpart should now be in the Web Part Gallery and ready to be added to a page.

One thing I also want to discuss is the different ways of adding a webpart to a page. These are:-

  • adding the webpart to a WebPartZone (possible in a feature by use of AllUsersWebPart element)
  • adding the webpart to the HTML markup of a page layout by dragging from SPD

The main thing to note is that if you want to be able to update webpart configuration as part of updating the page layout itself, the webpart should not be in a WebPartZone. If so, the webpart properties are stored in webpart storage, and updating a page layout (either via a feature or manually uploading to the Master Page Gallery) will not change any web part properties. However, note that web part properties can only be edited by a user if the part is in a WebPartZone. This confused me for a while, and is an important facet of the webpart architecture to be aware of.

37 comments:

Markus said...

This is a genius blog!
I was struggling exactly with the issue of how to deploy site customizations from development to production and you cover every aspect of it! This saves me a ton of time.

Chris O'Brien said...

Glad it's useful Markus ;-)

Thanks for the feedback.

C.

bk201173 said...

Could you please explain how to make the CAB file and the steps after that to take it to another server (say Dev or Production). I guess I am also looking for the steps as once the CAB file is made, what/how are the steps to take to deploy this CAB file on dev or prod server. I am really stuck here and if you could explain this, I really would appreciate it.

Chris O'Brien said...

bk201173 - I've just posted an article on this at http://sharepointnutsandbolts.blogspot.com/2007/07/building-and-deploying-sharepoint.html.

If there's anything that's still unclear, leave a comment over on that post.

HTH,

Chris.

Anonymous said...

Great Blog!!!
I have a question.
Can we deploy webpart to a particular site collection and not to all site collections in a web application?...

Thanx in advance

Chris O'Brien said...

Tahu,

Yes I'm 99% sure this is possible - you'll need to specify the URL of the site collection to target when you deploy the solution though (rather than specifying -allcontenturls).

Remember that the underlying assembly will still be deployed more widely than a site collection - either globally in the case of the GAC, or at least to web application scope if the web app's bin directory is used.

Cheers,

Chris.

Hammeq said...

Hello,

I deploy my web part in almost exactly the same fashion as described here. One problem I can't get around, though, is that the web part dll:s do not get deployed directly to the BIN folder in the web application, but rather in their respective folder, in the BIN folder. In other words, using your exact example, my DLL would end up in bin\COB.Demo.WebPartDeployment.WriteToFileWebPart\ rather than in just \bin. Do you know how to get around this?

Chris O'Brien said...

Hi Hammeq,

I don't remember seeing this behaviour when I wrote the article, but I just did some testing and you're absolutely right.

It seems the Assembly element in the manifest.xml file does not like the Location being set to a child folder for bin deployments. The solution is to amend the .ddf file so you have a different structure in the solution package (.wsp). If you keep the assembly at the root of the cab file (and amend the Assembly/Location attribute in manifest.xml accordingly), the assembly will be properly deployed to the root of the bin folder, not a subfolder. All other files can stay in the child folder within the .wsp, it's only the assembly which needs to be moved to the root.

I guess the reason why this hasn't been a problem for me is because we're happy to deploy web part assemblies to the GAC in our environment.

Apologies for the inaccuracy.

HTH,

Chris.

RightKindOfLove said...

i have a question but i cant post my sample code here, but its posted in another forum

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=3176344&SiteID=1

i have a feature receiver, which creates web part pages, and call custom web part for each pages created.

where web part always return null. but if i edit the created page and add the web part manually, the web part works fine. It seems when the web part is called from the feature receiver, it does not render.

Chris O'Brien said...

Hi,

I just took a look at your sample code at the link above but saw you already found the solution. Good stuff..

Chris.

Gujubhai555 said...

Great Post Chris, this helped me a great deal in automating the deployment of my web parts.

However I do have one problem. Once the feature is activated and I deactivate it, it doesn't remove those web parts from the web part gallery.

From what I know the web parts should be removed when a web parts feature is deactivated. Please help me.

Thank You,
Gujubhai555

Chris O'Brien said...

@Gujubhai555,

I think this is the expected behavior, web parts will not be removed from the gallery upon Feature deactivation.

You could build this in however, by using a Feature receiver to remove the parts from the gallery.

HTH,

Chris.

Sumit Kumar Domyan said...

Hi Chris,

Nice Article! Thanks for putting hard work on this. I've a question here.

Can I deploy a feature for a particular site collection or web application? I don't want other site collections or web applications to see it in their Features list.

Thanks,
Sumit

Chris O'Brien said...

Hi Sumit,

The answer is that it depends on what is in your Feature. The elements by scope table lists which Feature elements can be deployed to each level.

If you have deployed something to an individual site collection only, it won't show up in the 'Site Collection Features' list of another site collection.

HTH,

Chris.

Assefa said...

I don't think we can deploy a feature for a particular site collection or web application even if we pass specific site collection urls or webapps during wsp depolyment. We install Features in the 12\Template\Features directory. SO after installation we are going to see features everywhere regradless of its scope. The feature scope just defines the context where the feature can be activated and deactivated. We even see a feature in a web app that's created after feature installation. That's true again regradless of its scope. The urls/webapps that we pass during solution deployment determine where to put web app resource files, dlls,etc... not the feature itself. Basically that's how we insatll features. There are no sitecollection urls or webapps parameter
stsadm –o installfeature –filename (path of the Feature.xml file relative to the 12\TEMPLATE\FEATURES folder )

let me know if i miss something. I have spent some serious time looking into this issue and that's what i found out.

Thanks,
Assefa

Anonymous said...

Hey can i deploy multiple webparts as features in one goo ?

or

In one WSP can i have multiple webparts, which gets deployed as features.

< now i am posting as Anonymous >

Chris O'Brien said...

Yes you can - there are no restrictions (AFAIK) on the number of elements (e.g. web parts) in a Feature or number of Features in a solution.

Often grouping things together (if they are related functionality) makes the most sense.

HTH,

Chris.

cindy said...

Good article!

I have question. I have installed Sharepoint Services 3.0 in Microsoft Windows Server 2003 Enterprise Edition SPI. I open the SharePoint 3.0 Central Administration after installed. But, I cannot access to Operation and Application Management tab. It comes error : Access Denied!!

I would appreciate if you could tell me how to solve the problem.

thanks

Best Regards
Cindy Tan

Chris O'Brien said...

Cindy,

This could be due to either your account not having the correct SharePoint permissions (e.g. is it a farm admin?) or IIS settings on the Central Admin website. Suggest you try changing the latter to anonymous access as a test..

HTH,

Chris.

Chris said...

HI Chris,

Could you help me please.. I have created a CQWP in the GUI and exported it so i have cqwp.webpart. How can i then include this and change this to be added as a feature for easy deployment? I am struggling to figure out how to add it to the manifest etc...because its just an xml doc...

Thanks

Jagannath said...

Hi Chris,

Great post. Just took me a day to create a solution and deploy it in sharepoint. But I am facing an issue with a web part page. I use the Module/File tag to deploy the aspx file that has a webpart. But each time I redeploy the solution the web part keeps getting appended to existing stuff resulting in duplication. I guess this is because the aspx file is not deleted as part of undeploy. The aspx file is added as 'Ghostable' under root url(http://servername/my.aspx). How do I delete this file?

Jagannath

Chris O'Brien said...

@Jagannath,

Yes, I've seen this 'duplicate web parts' problem. I think it happens because the provisioning framework isn't really designed to deal with Feature re-activations in this way - it's mainly about the one-time provisioning of files. A couple of suggestions:-

- if you're only making changes to files defined in 'Module' elements, you should find that STSADM -o upgradesolution will update the .aspx but not cause the duplicate web parts.
- if you do need to re-activate the Feature (e.g. because you updated the Feature files), you'll probably need to script the removal of the duplicate web parts (using SPLimitedWebPartManager)

HTH,

Chris.

Chris O'Brien said...

@Chris,

So you have the .webpart file. Effectively you just need to follow the other steps detailed in this article to deploy it into the web part gallery so your customized version can be selected by users.

HTH,

Chris.

Anonymous said...

Ur article sux. First of all, ur examples are made as imgs, so it is impossible to copy the code. Second, they r cut and text is just partially visible. Third, there is a bug about

< metaData >
< type name="TitleWP.TitleWP, TitleWP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5" / >

The name must be strong with the PublicKeyToken.

I've spent the whole f-g evening trying to understand why my web-part doesn't work. Fix the bugs or remove the article, cause it is not just useless, its harmful.

BTW, the gj example:

http://www.theartofsharepoint.com/2007/05/how-to-build-solution-pack-wsp.html

Chris O'Brien said...

@Anonymous,

Thanks for the feedback. A couple of points:

- agree the code samples are less useful than they could be due to not being able to copy/paste. This article was written before it was easy to add code samples to Blogger, and unfortunately I've not had time to go back to rewrite some of my early articles like this one
- my code/XML samples are from a 100% working example, so whilst you might need a 4 part assembly name in your scenario, I'm pretty sure I didn't in mine. Agree that strong-naming is a good practice though, and of course mandatory if deploying to the GAC

Since others have left positive feedback on the article, afraid I'm not going to be removing it based on your opinion. Sorry you didn't find it useful.

Chris.

Anonymous said...

I agree, the post is informative but cannot be copied nor any sample was provided for download. Overall, the post was good. I don't want to criticize you. I still had to search looking for more information and found a similar one -
http://www.dotnetmafia.com/blogs/dotnettipoftheday/archive/2008/10/22/intro-to-sharepoint-development-how-to-build-and-deploy-a-web-part.aspx

Nimish Agarwal said...

Hi Chris,

I know two ways of deploying the web parts to the web part page.

1. Copying the web part .dll to the bin folder, adding safety tag to the web.config and then adding to the web part page.

2. Creating the .CAB file and then installing using stsmd command and then adding the web part to the web part page.

Both the above methods requires access to the server on which the sharepoint is installed and running.

Is there any way we can deploy the web part directly from the Sharepoint site without access the server?

Thanks,
Nimish

Sagar said...

Hi Chris,

Basically I need to deploy web parts on share point server, but the issue is I dont have any access to the server.

Is there any way to do it

Thanks
-Sagar

Chris O'Brien said...

@Nimish,

If you mean you want to make a new web part available for selection without going through someone who has access to the server (e.g. an administrator), then I'm afraid the answer is no.

Generally your number 2 approach is the one used - if a web part could be made available without this process it would be a huge security/stability risk in most environments :-)

HTH,

Chris.

Chris O'Brien said...

@Sagar,

See previous comment to Nimish :-)

Chris.

aman said...

Hi Chris,

I have a query. Suppose I am deploying a dll to GAC as well as to BIN folder.Then how to make out whether the dll from GAC is used or DLL from Bin folder is being used.

Chris O'Brien said...

@Aman,

My first question would be why do you want to deploy to both the bin directory and and the GAC? I can't really think of a valid case for this and am not even sure the .wsp framework supports it.

In any case, for loading assemblies in the normal manner, .Net will always load assemblies from the GAC first, since this location is 'probed' earlier than the bin directory.

HTH,

Chris.

Ven said...

Hi Chris,
Where is the .ddf file? Also it would be great, if you could show this in a sample project with more screen shots.

Regards,
Ven

Chris O'Brien said...

@Ven,

A couple of things have moved on since this article - I'd now recommend using WSPBuilder which will create the manifest.xml, ddf file and create the WSP package from these for you. It's a very popular tool in common usage for SharePoint 2007 development, and removes the need to mess around with ddf files.

You still need the feature.xml and feature elements file though.

HTH,

Chris.

Robert Rakowitz said...

The given xml examples make no sense, since you are deploying the Webpart via the Solution (.wsp). When you include the in the solution you don't need the whole feature anymore.

On the other hand you can deploy the webpart using the feature by not including the Tag in solution XML.

Using the feature deployment you can also activate it for specific SiteCollection or even Sites (Webs) only.

Chris O'Brien said...

@Robert Rakowitz,

In what way do the XML examples not make sense? If you're using a tool to generate some of these files in the background (e.g. WSPBuilder, STSDEV, WSeWSS) then I agree *you* do not need to create them (e.g. manifest.xml, in the first screenshot), but something does! This article is coming up to 3 years old and such tools were either not around or in common usage at that time which might explain something.

I'd love to go back and update articles like this with newer techniques, but then I'd never write new articles and feedback suggests that's more useful to most of my readers. That said, I discussed more up-to-date techniques quite recently in My Favorite SharePoint 2007 Development Techniques (with an eye on SP2010).

Hope that's of some use.

Chris.

Christine said...

your articles are awesome chris