Developing SharePoint WebParts using User Controls and Web Applications

104

Category : featured, sharepoint, webpart, wspbuilder

If you’ve read my blogs before, then you probably know I am a fan of WSPBuilder (http://www.codeplex.com/wspbuilder). I like the intuitive nature and flexibility of the product. It really helps with the deployment aspects of SharePoint features and functionality. However, in the end, it is really just a structured way to create a deployment/feature project that will create the wsp install file for SharePoint. It really doesn’t help much when building UI functionality. For example: if you want to build a Web Part in SharePoint, you still have to build the Web Part code out programmatically (instead of using the WYSIWYG features of Visual Studio). The same issue comes up with building master pages, application pages or anything that requires html and a code behind.

In this article I am going to show you how you can utilize the flexible nature of WSPBuilder, ASP.Net Web Applications and post build scripts in order to utilize WSPBuilder as your deployment project for your UI. 

Solution Overview

SharePoint is a dynamically generated website that pulls information out of a database. It also utilizes files on the server and uses those files as templates or actionable files. The combination of these static files on the server and the information in the database creates the web page we see. This architecture is what allows us to create pages, add webparts, modify navigation, etc… all within the SharePoint site itself.

So, when developing against SharePoint, we need to deploy files to this static place on the server and register the files in the database. This static place on the server is called the 12 hive. It is usually found at: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12. A lot of stuff goes on in the 12 hive. You have the templates for the website, images, themes, etc… You also have very special items called Features. Features allow us to deploy custom functions to SharePoint and then activate/deactivate them at our leisure.

WSPBuilder allows us to “mimic” the 12 hive, within a Visual Studio project. As long as you have the same 12 hive structure setup, it can create the SharePoint deployment file (i.e.: the wsp). You do not need WSPBuilder to create wsp files; you can do the same thing by building extra files in your solution called manifest.xml and ddf files. However, for rapid application development, it is easier to use a third party solution like WSPBuilder because it creates those extra deployment files for you.

While WSPBuilder is a great tool to help us build the deployment files, it is not a web application project in Visual Studio. Web application projects help us build code behind and designer files for our server side controls.

Thus, the ideal solution for building UI elements in SharePoint consists of:

  1. ASP.Net Web Application project to build the UI elements
  2. WSPBuilder project to create our deployable wsp file

The ASP.Net Web Application project will contain the UI elements (such as User Controls). The build process will move the appropriate elements from the ASP.Net Web Application project to the WSPBuilder deployment project. Then the deploy will move the files from the wsp to the SharePoint Server.

Deploy

The key to this solution is seperation of concerns. You should build all UI related functionality in the ASP.Net Web Application project. All SharePoint specific functionality (ex: features), should be built in the WSPBuilder project.

 

Create the WSPBuilder deployment project

  1. Create your project in Visual Studio (File – New – Project)
    • Choose the WSPBuilder project. I am utilizing the one under c# for this example.
    • Give it a good name. I am using DemoProject for this example.
    • Make sure it creates a new solution when creating the project.
  2. Add a folder under the 12 folder called “Template”.
  3. Add a folder under the Template folder called “LAYOUTS”.
  4. Add a folder under the Template folder called “FEATURES”.
  5. Add a folder under the Template folder called “CONTROLTEMPLATES”.
  6. Add a folder under the project called “GAC”.

Note: The “GAC” folder in WSPBuilder is a special folder. We can place external dlls in this folder the the resulting WSP will deploy those dlls to the GAC for us.

DemoProject

 

Create the UI project

As I mentioned in the beginning of this article, the point is to create our UI elements in an ASP.Net Web Application project. So, we need to create another project, in the same solution, so that we can develop our UI elements.

  1. Create the UI project (File – Add – New Project)
    • Choose the ASP.NET Web Application Template. I am utilizing the one under c# for this example.
    • Give it a good name. I am using DemoProjectUI for this example.
  2. Delete the Default.aspx
  3. Sign the project (this is because we are going to deploy to the GAC)
    • Go to the properties (right-click the project and choose properties).
    • Go to the Signing tab.
    • Choose “Sign the assembly”.
    • Under the “Choose a strong name key file” – choose <New>
      • Give it a strong name – I usually use the name of my project (for example: DemoProjectUI).
      • Uncheck “Protect my key with a password”.
  4. Add in the post build commands
    • Go to the properties (right-click the project and choose properties).
    • Go to the Build Events tab.
    • Add the following into the post build section:
      xcopy "$(TargetPath)" "$(SolutionDir)DemoProject\GAC\" /Y /s
      xcopy "$(ProjectDir)*.ascx" "$(SolutionDir)DemoProject\12\TEMPLATE\CONTROLTEMPLATES\" /s /Y /R

Let’s recap what we did in the steps above. First we created a WSPBuilder project called DemoProject. This is our deployment project. It will create wsp files that we can deploy to SharePoint. Then we created an ASP.Net Web Application project called DemoProjectUI. This is where we will create all our UI elements. This will allow us to create user controls with html and code behind files. Lastly, we made sure that we moved the dll and ascx files, from the DemoProjectUI project, to the appropriate place in the DemoProject project.

 

Create a Web Part

Our next step is to create a Web Part. As anyone who has developed in SharePoint before knows, Web Parts are complete code files. They are not the html with code behind files we are used to when developing in ASP.Net. Some people are fine with developing Web Parts completely programmatically. However, it is much easier to create UI elements when you have WYSIWYG editors, html and code behind.

One way to get the normal ASP.Net web development experience, when developing Web Parts, is to use the SmartPart. The SmartPart is a very clever Web Part, developed by Jan Tielens, which can render .Net user controls in Web Parts. I really like the SmartPart, especially for people learning to build SharePoint Web Parts as user controls. However, I like more control over what I do and there are some limitations to the SmartPart. It is not my intent to go over those limitations in this article, but you can read them here: http://weblogs.asp.net/erobillard/archive/2008/03/04/what-to-know-about-smartpart-and-loadcontrol.aspx

In the end, you can accomplish the same thing as the SmartPart using the “LoadControl” method in .Net. Thus, this article will show how to create a Web Part, which will load the user control from our UI project.

  1. Create the Web Part using WSPBuilder
    • Right-click on the DemoProject project
    • Go to Add – New Item
    • Choose WSPBuilder – Web Part Feature
    • Give it a good name. For this example I am going to use DemoFeature
    • A popup will come up with Title, Description and Scope. Since we are developing a Web Part, you must choose “Site” for the scope. This is because we need the Web Part to deploy to the Web Part gallery of our Site Collection.

    Notice that WSPBuilder did two things for you:
    - It created the feature in the features folder
    - It created the Web Part code in a folder called WebPartCode

  2. Modify the Web Part code to use “LoadControl”
    • Open up the DemoFeature.cs file in the WebPartCode folder
    • Remove the MyProperty property and attribute for now. This is just WSPBuilder showing you how you can use properties. We aren’t going to use them for this demo.
    • Find the CreateChildControls method and find the comment that says “Your code here…”
      • Remove the line under it.
      • Replace it with this: this.Controls.Add(Page.LoadControl("~/_controltemplates/DemoControl.ascx"));

      Your CreateChildControls method should look like this:
      protected override void CreateChildControls()
      {
          if (!_error)
          {
             try
             {
                base.CreateChildControls();
                this.Controls.Add(Page.LoadControl("~/_controltemplates/DemoControl.ascx"));
             }
             catch (Exception ex)
             {
               HandleException(ex);
             }
          }
      }

  3. Add the control to the UI project
    • Right-click on the DemoProjectUI project
    • Go to Add – New Item
    • Choose Web – Web User Control
    • Give it a good name. For this example I am going to use DemoControl.ascx

Now, when you build your solution, the DemoControl.ascx will move to the ControlTemplates folder in the DemoProject project. The SharePoint Web Part will look for the control by using the _controltemplates path.

Note: SharePoint can find any control in the ControlTemplates folder by using the _controltemplates path because of a mapping it creates in IIS. SharePoint maps the _controltemplates path to the servers 12 hive at 12/Template/ControlTemplates.

 

Utilizing the Code Behind

We now have our basic solution setup. We have our UI project and can build our user control there. We have our WSPBuilder deployment project that will create our SharePoint install file. But, we aren’t ready to deploy just yet. We still need to tell our user control how to talk to its code behind. Because we are utilizing the GAC for our assemblies, we need to put a fully qualified domain in our ascx file. There are a couple of techniques for figuring out this fully qualified domain. What I like to do is deploy the project and go to the GAC to get the properties.

  1. Deploy the WSP, so that the assembly gets added to the GAC, so that we can pull out the assembly information.
    • Right-click on the DemoProject project
    • Click WSPBuilder – Build WSP (wait for it to finish)
    • Right-click on the DemoProject project
    • Click WSPBuilder – Deploy WSP (wait for it to finish)
    • Get the assembly information from the GAC
      • Usually found at C:\Windows\assembly
      • Right-click on the DemoProjectUI assembly and click properties
      • Note the public key token and version ( I suggest copying the public key token at this point because we are going to use this information in the next step).
  2. Add the assembly information to the ascx
    • Go to the DemoControl.ascx file in the DemoProjectUI project
    • Add an Assembly reference as the first line in this file. Below is an example. However, you cannot copy this example. Your assembly reference must have the correct information about your assembly (including your public key information).


<%@ Assembly Name="DemoProjectUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=772ab5f02712b819"%>

 Now we are ready to test our solution!

 

Deploy the Solution

Now that we are finished setting everything up, we can deploy the solution. This is real easy with the use of WSPBuilder as long as we are developing on a SharePoint server.

Note: Please make sure you have a web application and site collection setup in SharePoint before doing the following steps. When you deploy the WSP solution, it will deploy to all web applications on your development server. Thus, the web application must exist before you deploy.

  1. Right-click the DemoProject project
  2. Click WSPBuilder – Build WSP (wait for it to finish)
  3. Right-click on the DemoProject project
  4. Click WSPBuilder – Deploy WSP (wait for it to finish)
  5. Open up your SharePoint site.
  6. Note: if you go to the SharePoint site at this point and it says “Server Not Available”, then just keep refreshing the page until it shows up. The WSP install recycled the application pools because it needs to every time a dll in the GAC is added or modified. It sometimes takes a few seconds for this process to finish.

  7. Go to Site Actions – Site Settings
  8. Go to Site Collection Features
  9. Activate the DemoFeature
  10. Go back to the site
  11. Go to Site Actions – Edit Page
  12. Click “Add a Web Part” in one of your web zones
  13. Find your WebPart. It should be under “MyGroup” unless you changed the group name in your feature. The elements.xml file in the feature folder of the DemoProject lets you configure this information. I
  14. Add your Web Part to the page

At this point your Web Part is empty because we didn’t add any html or code to it. However, you solutions architecture is ready to go. Now you can go back to your User Control, do your development, deploy the solution and it will show up on your page. Let’s give it a try.

  1. Go to the DemoProjectUI project
  2. Open the DemoControl.ascx
  3. Put a label tag on the control
  4. <asp:Label runat="server"  ID="test" />

  5. Go to the code behind (i.e.: DemoControl.ascx.cs)
  6. In the Page_Load type the following
    protected void Page_Load(object sender, EventArgs e)
     {
          test.Text = "Hello World";
     }
  7. Right-click the DemoProject project
  8. Click WSPBuilder – Build WSP (wait for it to finish)
  9. Right-click on the DemoProject project
  10. Click WSPBuilder – Deploy WSP (wait for it to finish)
  11. Open your SharePoint site and see your Web Part. It should say “Hello World”.

Remember: if it says “Server Not Available”, then keep refreshing the page until the site shows up again.

Wow, that was a lot of setup just to create a user control that can render in a Web Part. But, the great thing is, you only have to do the setup once. As a SharePoint Architect, I set this up for my team and they can just concentrate on building the user controls. It runs very smooth!

Per popular demand, here is the demo solution from the walkthrough. I used Visual Studio 2008, WSPBuilder Extenstions 1.0.5 and .net 2.0 for this solution (I used 2.0 so it can work for a client of mine, it can be upgraded to 3.5 easily)
DemoProject

Moving a sharepoint workflow between solutions – "Failed on Start (retrying)"

10

Category : Workflows, sharepoint, wspbuilder

The following blog is talking about an issue I had with moving a workflow. It does not talk about how to create workflows. If you want some really good information on that you can find some great tutorials by Robert Shelton here http://rshelton.com/archive/2007/10/05/sharepoint-document-workflow-with-visual-studio-workshop-documents-download.aspx. I really recommend going through his walk-throughs if you are learning how to build SharePoint workflows in Visual Studio 2008.

Today I attempted to take a workflow built with Visual Studio 2008 and move it to a WSPBuilder workflow. The reason I wanted to do this was because I had a nice Visual Studio solution for SharePoint already going utilizing WSPBuilder. Plus, the Visual Studio workflow solutions make it hard to deploy the association aspx pages easily without another web project.

Here are the details of the two solutions:
Solution 1 (original) – built with the Visual Studio 2008 SharePoint Sequential Workflow template
Solution 2 (new) – built with Visual Studio 2008 WSPBuilder.

So, to start I created a new sequential workflow in WSPBuilder and this built out my feature and initial workflow. Next, I created my aspx page in the layouts folder (this is the association page for my workflow). Next, I created the .cs page that will be the code behind for this aspx page. Now, this isn’t like a regular code behind because we aren’t in a web project and we are using SharePoint. This code behind will be in the GAC and the aspx page needs to reference it like this:

<%@ Page language=”C#” MasterPageFile=”~/_layouts/application.master” 
Inherits=”DocumentAssociationForm, DocumentApprovalWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5017f6ecf55b35e7″  %>

Notice my “Inherits” points to the assembly information and my MasterPageFile points to the application.master (because this page will live in the _layouts folder.

Now that I have my association pages built I needed to build out the workflow. I copied over the workflow I created in the original solution and placed it in the WorkflowCode folder (replacing the file that was put there by WSPBuilder when I created the workflow feature). Then I just made sure my feature.xml and elements.xml file were configured correctly to run this workflow. So, at this point I thought everything was ready to go. I used WSPBuilder to deploy my solution and I activated my feature on the site. I instantiated the workflow with my association data form I created and I was ready to test the workflow out. I went to run the workflow on an item in my list and I got this error: “Failed on Start (retrying)”. This made no sense to me because the same workflow worked fine from my original solution. So, was WSPBuilder causing the error? Did I mess up something? I really didn’t know. I then went to the SharePoint logs and found this error in them: “The workflow failed validation”.

Ah, my first clue. When a workflow fails validation, that usually means a .rules file is messed up. But, my .rules file seemed to be setup just fine. So, back to the drawing board.

After eliminating every possibility I went and took a look at the project files (.csproj) and I opened them up in notepad. I compared my new solutions file against my old solution and I noticed something. At the very end of the file on the original solution there was this line:

<Import Project=”$(MSBuildBinPath)\Microsoft.CSharp.targets” />
  <Import Project=”$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.5\Workflow.Targets” />

But, this was not in my new solution. So, it looks like the project file didn’t get notified to work with WF and version 3.5 specifically. I fixed the project file manually and everything worked.

Wow, that was a pain. But, in the end I have this workflow integrated into my larger solution so everything gets deployed at the same time. Thus, I don’t need a separate project just for my workflow and I don’t need a separate project just for my association form. It is really nice, but I almost put my head through the wall figuring it out.

Developing SharePoint Solutions in Visual Studio

80

Category : sharepoint, wspbuilder

SharePoint is built on top of .net, but is not like a regular webpage. SharePoint uses a process of storing information in databases and using files on the server (in the 12 hive – which we will talk about later). When a SharePoint site is created it uses the files in the 12 hive to dynamically create all the information in the database to create the actual site. Some of the information it stores in the database is just references to files on the server (in the 12 hive). Thus, when developing for SharePoint we should modify the files in the servers 12 hive to create customizations (actually, we should never modify the out-of-the-box files on the 12 hive, we should just create new files for our customizations). This way our SharePoint pages will have references to our custom files in the servers 12 hive and will use those custom files to create the site, as well as keep the references to these custom files. Keeping these references around is a concept call ghosting. If you try to customize SharePoint any other way (SharePoint designer, site templates, etc…) you will un-ghost your site. This basically means you are losing the references to the 12 hive and it makes a copy of everything directly in the database. This can be a bad thing because you won’t have one place to make changes for all your sites. On a side note: I have heard the argument un-ghosting is not that bad because of master pages (as long as all your sites reference the same master page). I don’t buy this argument, because there are changes you can make outside of the master page that you want to keep ghosted still. An example of this would be your web zone layout in your aspx pages.

So, you can create site definitions and features in .net and push them out to the servers 12 hive in order for SharePoint to use them. Site definitions are custom xml files and aspx pages that create the webpages for SharePoint and reference the Features to activate within the SharePoint site. Features, which can be activated on the site definition, wrap all the actions we can do on SharePont. If you want to create lists – wrap them in a feature that can be activated. If you want to create webparts – wrap them in a feature that can be activated. Basically, if you want to create things in SharePoint – wrap them in a feature that can be activated. One of the great advantages of building custom Site Definitions is that we have complete control over which features get automatically activated on our site (thus, the features do not have to be manually turned on in the SharePoint site settings).

Site Definitions should always be used to create sites if you want to do true development modifications. You should not use Site Templates if you are a developer (believe me, you will regret using Site Templates if you ever have to modify them or if something goes wrong in them). SharePoint is built upon this concept of Site Definitions and Features for all of the out-of-the-box sites that you can create. Thus, following the SharePoint model of creating Site Definitions is the best option available to us as developers.

Below I am showing how to create a custom SharePoint solution in Visual Studio. I am leveraging a third party tool called WSPBuilder. Using WSPBuilder, or any third party tool, is not required to build solutions, but I have found that it makes life easier. This solution will create features and site definitions and package them up into a wsp file. A wsp file is like an install file for SharePoint (in fact, it actually is a cab file renamed). The acual feature we will be creating in this demo is a feature to deploy a master page to the master page gallery in the SharePoint site. However, following these techniques you can deploy any feature and activate it in a site definition.

1.   Installs

      The recommended way to develop in SharePoint is a Virual Environment – whether VPC or VMWare or any other kind of Virtual Environment. The reason is you need to develop on a SharePoint machine which needs to be on a server. And, it is really hard to get a dedicated server machine just to develop on. If you want to share a server with other developers it is really hard to develop in SharePoint because of the constant App Pool Recycles that are needed. Also, a virtual environment lets us make backup points for the whole server, so if we mess up the environment we have a good snapshot to roll back to. Thus, a virtual environment, in which each develop can have their own virtual server, with their own virtual SharePoint environment is the best way to develop in SharePoint.

a.      WSS or MOSS server

b.      Visual Studio 2005 or 2008

c.      WSPBuilder (version 1.01)

 

2.    Start Visual Studio and choose a new WSPBuilder project.

 

 

3.    Create a folder structure for the solution that matches the folder structure for the SharePoint 12 hive (this is really important – WSPBuilder works on the premise that the Visual Studio solution matches the structure of the SharePoint 12 hive). For now we are just going to create the following folders:

a.   1033 – holds the xml files that will tell SharePoint about our new site definitions

b.   Features – holds the new features we are going to build (i.e.: lists, webparts, master pages, etc…)

c.    Layouts – holds our reference files (i.e.: images, css, js, etc…)

d.   Site Templates – holds our site definitions

 

Server 12 hive structure

 

 

VS Solution

 

 

4.       Create a new site definition based off the team site definition in SharePoint.

a.   Copy the team site definition folder from the 12 hive:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\SiteTemplates\sts

b.   Paste the folder in the Visual Studio solutions SiteTemplates folder.

c.   Rename the sts folder to something unique (DemoCompanySiteDef for this example)

d.   Delete the defaultdws.aspx file because we aren’t going to use it for this example.

 

e.    Open the default.aspx file and change the master page to a new master page. Call this custom.master (yes, I know that this is not the name of our master page. We are going to configure SharePoint to do a string replacement of custom.master with DemoCompany.master in later steps). We will create this master page in the next step.

 

f.     Open the Onet.xml file (located in the xml folder) and clean it up for our simple site definition.

The Onet.xml file is the file that tells SharePoint how to create the site definition. Whenever you create a new site in SharePoint it reads from the Onet.xml file to determine how to create the site. It is important to note that SharePoint is reading from the Onet.xml file when the site is being created. So, if you already have created a site, you can’t go back to the Onet.xml file, make changes, and expect it to show up on your already created sites. On a side note: I heard that Onet stands for Office Net.

                                   i.     Scroll down to the Configurations XML nodes and remove 2 configurations:

1.       ID=1  - Blank

2.       ID-2 – DWS

      Be very careful not to remove ID=0 – Default because this is the configuration we are going to use for this site definition. When removing the other two get rid of the whole xml tag as well as everything within their xml tag.

                                   ii.    Scroll down to the Modules XML nodes and remove 2 modules:

1.       DefaultBlank

2.       DWS

      Once again, be very careful not to remove the Default module because this is the module we are going to use for this site definition. When removing the other two get rid of the whole xml tag as well as everything within their xml tag.

5.    Create the new master page feature

The master page will be created as a feature. The reason for this is that if the master page is in a feature the page can be added to the master page gallery of SharePoint. This allows you to set out-of-the-box pages to the master page or your own custom site definitions. It also allows you to turn on or turn off the master page features on specific sites. Basically, having it in a feature (rather than directly in the site definition or in the layouts folder) gives you much more flexibility.

a.    Create a new folder under features and call it something unique for your master page. For this example we will call it DemoCompanyMasterPage.

b.    Create a folder under the DemoCompanyMasterPage called “MasterPages”.

                            i.      Copy the general SharePoint master page from the 12 hive: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\GLOBAL\default.master

                           ii.      Paste the file under the “MasterPages” folder in the Visual Studio solution.

                           iii.     Rename the file to something unique (DemoCompany.master for this example).

c.      Create two xml files under the DemoCompanyMasterPage folder.

                           i.      Feature.xml – this will give a unique GUID to the feature (which we will reference later). This file also gives some important information about the Scope of the feature. Lastly, this file tells SharePoint where all the other files that make up this feature lives. This file must be called feature.xml (this is because SharePoint will read all files called feature.xml from the Features folder).

Please note that the Scope=”Site”. This is very important. This is telling SharePoint that this feature is for the site collection. If that Scope=”Web” then it would be telling SharePoint that this feature is for an individual site.

 

                           ii.      Elements.xml – this file is telling SharePoint to place the new master page into the master page gallery. This file does not have to be called elements.xml (unlike the feature file which has to be called feature.xml). It just has to match the name located in the “ElementManifest” of the feature.xml file.

 

6.    Modify the site definitions onet.xml file to tell the site to install and use this new masterpage feature when a new site is created.

a.    Open the onet.xml file in Visual Studio (located at SiteTemplates/DemoCompanySiteDef/xml).

b.     Find the xml node that says Configuration ID=0 Name=”Default”.

c.     Add in a reference for the new master page: 

Note: SharePoint will do a string replacement of any aspx page with ~masterurl/custom.master with the reference in CustomMasterUrl. And, it will replace any aspx page with ~masterurl/default.master with the reference in MasterUrl.

d.   Find the SiteFeatures XML node.

e.   Add a new Feature node in there that matches the GUID of the feature.xml file we created for our master page.

 

This section of the onet.xml basically tells the site to activatethis particular feature on this particular site when it is being created. The reason it goes into the SiteFeatures (instead of the WebFeatures) is because this particular feature was scoped for a Site Collection (refer to step 5c where we created the feature and scoped it for a Site Collection). If the feature was scoped for an individual site then it would go in the WebFeatures.

 

7.    Create the WebTemp*.xml file

WebTemp*.xml files tell SharePoint about site definitions. When a new site is being created in SharePoint the “Select Templates” list box is populated by anything it can find in the WebTemp*.xml files. There can be multiple of these files in SharePoint as long as they are in the 12/Template/1033/XML folder. SharePoint will basically read this folder for any file that starts with the word WebTemp.

a.    Add a new folder under 12/Template in our Visual Studio solution called 1033. Then, add a new folder under 1033 called XML.

b.    Add a new file to the 12/Template/1033/XML folder in our Visual Studio solution. This file must start with WebTemp. We will call this file WebTempDemoCompany.xml.

 

c.       Add in the proper xml to tell SharePoint about our new site definition

 

A few things to note:

-    The Name must match the site definition folder exactly. We used the name DemoCompanySiteDef. This matches our site definition name exactly.

 

-    The Configuration ID must match the configuration ID in our onet.xml file of our Site Definition. We used configuration id 0.

-     The display category will create a new tab on the new site screen in SharePoint.

-     The ID has to be unique and SharePoint has already reserved certain IDs. To be safe use an ID over 10000 and make sure it is unique.

 

8.    Now, at this point (in a regular SharePoint solution) we would create manifest.xml and ddf files. These are files SharePoint needs to install the solution properly. However, since we are using WSPBuilder, it will do that for us.

a.     Right click the project and click WSPBuilder – Build

 

b.    Verify your Web Application is created on your local SharePoint environment. Note: the Site Collection should not be created at this point, just the Web Application. And, you only need to do this once.

c.     If the build is successful, right click the project and click WSPBuilder – Deploy.

This is needed because the build command in WSPBuilder just builds a wsp file. This file can be sent to other machines and you can use stsadm scripts to install it on other SharePoint farms. However, in development, we need a quick way to deploy it to the current SharePoint farm. The WSPBuilder – Deploy command will deploy the wsp file on all the Web Applications in the local SharePoint farm.

 

9.    Open up SharePoint Central Administration and create a new Site Collection with the site definition we just created.

 

Now you can go back and modify the master page or default.aspx page as you wish. Just be careful not to mess with the ContentPlaceHolders too much. SharePoint reserve these for certain actions on some of its internal pages. After every change you make you can rebuild by clicking WSPBuilder – Build and update the solution by clicking WSPBuilder – Deploy. Then you can just go to the website and see your changes. Just be aware that everytime you deploy WSPBuilder does an app pool recycle (to ensure the changes get pushed out through IIS), so you might have to wait a few seconds to see your changes (during that few seconds the site could say Service Unavailable).

It is also important to note that the first time you deploy with WSPBuilder it does a true SharePoint install. However, every subsequent time it does a SharePoint solution update. Solution updates work for most changes, however, there are some things it can’t do. So, if you run into errors it is sometimes good to do WSPBuilder – Uninstall and then a WSPBuilder-Deploy to do a real install in certain situations when you are making changes.

If you are curious to what a SharePoint solution is doing, then just check out the files in the 12 hive:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12

You will notice that all the files we created in our Visual Studio solution have been “pushed” down to the folders in the 12 hive. The WSP knows to “push” these files there. The WSP also knows to tell SharePoint that these files exist. This is exactly how SharePoint develops it’s out of the box site definitions (they are all located in the 12 hive and you can actually go and see them).

Because this blog is starting to get long I am not going to show how to create other features, but the principals are the same:

-      Create the feature and note the “Scope” you set it to

-      Go to your Onet.xml file, of your site definition, and place a reference to the GUID of the feature in the appropriate xml tag (SiteFeatures or WebFeatures).

-      Now that feature is associated with the particular Site Definition every time a new site is created with the selected Site Definition

The other features you can create in SharePointis a pretty long list. These include custom lists, webparts, custom actions, features that call other features, custom code that runs after another feature is created, etc… The key point I am making in this blog is that when you learn how to create another type of feature, you can just added into this solution and tie it to your site definition in the onet.xml file.

Side Notes:

1.    Any file you place in the Layouts folder can be reference in the aspx pages as “/_layouts/{filename}”. I usually recommend placing another folder under Layouts in the Visual Studio solution (just because it makes it easy to find later – you can call this folder the name of your company or the name of your project or anything that is obvious that it contains your custom reference files). Then you can reference everything in there by “/_layouts/{folder}/{filename}”. An example of this is css files in the master page. This is possible because SharePoint sets an IIS path up to the Layouts folder in the 12 hive and calls it _layouts.

2.    If you want to create a custom webpart with WSPBuilder just click Add – new item… WSPBuilder – WebPartFeature. This will create the feature folder, for your webpart, and the .cs class for your webpart. This way you can go directly into coding and not have to worry about the Feature creation. Once you are done coding the webpart just make sure it is in the appropriate scope of your onet.xml file (SiteFeatures or WebFeatures) and it will become available to you in your webpart gallery. Then all you have to do is worry about your dll being installed in the Bin or GAC. If you choose GAC I recommend post-build scripts to move it.

3.    Do not remove Content Place Holders from your master page if you start doing customizations. The reason for this is if you assign other files in SharePoint (such as list pages) to use your master pages, they will assume certain Content Place Holders exist. If they are not there, your site will just break.

 

Update
Since I wrote this I was informed that my demo only works for the top level page (i.e.: the site collection). If you use the code above on a sub-site, it won’t work. The reason is the example deals with the “Site” scope only. There are two ways to fix this for sub-sites:

1. Change the example to “Web” scope. This will place the master page in the master page gallery for each sub-site. To do this you need to change the feature.xml file to scope=Web. And, you need to change the onet.xml file to have the feature registered under the “WebFeatures” instead of the “SiteFeatures”.

2. In the Configuration node of the onet.xml, where we set the CustomMasterUrl and the MasterUrl to _catelags/masterpage/DemoCompany.master – we should replace those to point to ~SiteCollection/_catalogs/masterpage/DemoCompany.master. This approach will just point all the site definitions to use the master page at the root site collection level.�