Extend the Search Box web part in SharePoint 2010
Introduction
With SharePoint 2010 you can now extend the out of the box web parts, which essentially means you can create a new web part that inherits from one of the out of the box ones. In this post, I demonstrate extending a SharePoint Web Part in depth, using the search box as an example. First, let's take a look at the search box web part.
Find the Class
Since we will be inheriting from this web part, the first question we need to answer is: What is the class name of the web part I'm trying to extend? The answer isn't straightforward. The SharePoint Web Part Gallery doesn't provide this information, so it's not readily apparent by looking at the web part in design mode.
One way to find out is to add the web part to a page. In this case, from the Web Part gallery select the web part "Search Box" from the Category "Search". On the upper right corner of the web part, click on the drop down arrow and select "Export..."
This will prompt you to save the Web Part Definition file (.dwp). Open this file in a text editor and look for these two XML elements: Assembly and TypeName. In our case, the values are:
<Assembly>Microsoft.Office.Server.Search, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
<TypeName>Microsoft.SharePoint.Portal.WebControls.SearchBoxEx</TypeName>
This tells us a few things:
- The class name for this web part is SearchBoxEx, which is what we have to inherit from.
- It resides in the Microsoft.Office.Server.Search assembly.
- It's part of the Microsoft.SharePoint.Portal.WebControls namespace.
You can confirm this by looking at the SearchBoxEx documentation. We have two namespaces involved here because SearchBoxEx is implemented in Microsoft.Office.Server.Search, but it inherits from Microsoft.SharePoint.Portal.WebControls.WebPartLoc. With a little digging around, I found that these two namespaces are in:
Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.Office.Server.Search.dll
Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\microsoft.sharepoint.portal.dll
As it happens, these are not listed in the .NET tab of the "Add Reference" dialog in Visual Studio, so you will have to browse for them manually.
Create the project
Create a new project using the Empty SharePoint Project template and add a new Web Part to it. I called mine SearchBoxExtension. Your class definition should look like this:
public class SearchBoxExtension : WebPart
As with every inherited web part, start by calling base.CreateChildControls:
protected override void CreateChildControls()
{
base.CreateChildControls();
}
Add the assembly references using the Browse tab to locate the two DLLs. Your references should look like this:
Inherit your new web part from Microsoft.SharePoint.Portal.WebControls.SearchBoxEx (the TypeName value) instead of WebPart:
public class SearchBoxExtension : Microsoft.SharePoint.Portal.WebControls.SearchBoxEx
Build and deploy your project and try to add your new web part to a SharePoint page. You should get this error:
.dwp vs .webpart
What's the problem? Here's what just happened. Both .dwp and .webpart file types are XML web part descriptors that are deployed with your web part. The Dashboard Web Part (.dwp) format was used in earlier versions of SharePoint, where web parts inherited from Microsoft.SharePoint.WebControls.WebPart. The newer .webpart format, which supersedes .dwp, is what you use when you inherit from System.Web.UI.WebControls.WebParts, which is what you should always do when developing brand new web parts. For this reason, when you create a new web part in Visual Studio 2010, it automatically creates a .webpart descriptor for you:
SharePoint 2010 comes with a mix of older and newer web parts, so the descriptors that go with them might be either .dwp or .webpart. As you might've guessed from its namespace, Microsoft.SharePoint.Portal.WebControls.SearchBoxEx is one of the older ones and therefore requires a .dwp descriptor. The error we just got is therefore telling us that it doesn't like SearchBoxExtension.webpart.
Create the .dwp descriptor
So how do we get the .dwp file?
There are two ways:
- Create it manually
- Modify the .dwp exported from the original class
To create it manually, use SearchBoxExtension.webpart for reference. First, add a new XML file to your web part and give it the same name but with a dwp extension. Your web part folder should look like this:
Corey Roth has a nice post that compares the differences between the two formats. First, let's look at SearchBoxExtension.webpart:
<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="https://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="SearchBoxTest.SearchBoxExtension.SearchBoxExtension, $SharePoint.Project.AssemblyFullName$" />
<importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">SearchBoxExtension</property>
<property name="Description" type="string">My WebPart</property>
</properties>
</data>
</webPart>
</webParts>
By looking at the differences between the two formats, mapping the values from one to the other was relatively straightforward. Let's look at the result first:
<?xml version="1.0" encoding="utf-8"?>
<WebPart xmlns="https://schemas.microsoft.com/WebPart/v2">
<Assembly>$SharePoint.Project.AssemblyFullName$,Version=1.0.0.0,Culture=Neutral,PublicToken=ed9dffbe9e0cad7e</Assembly>
<TypeName>SearchBoxTest.SearchBoxExtension.SearchBoxExtension</TypeName>
<Title>SearchBoxExtension</Title>
<Description>My WebPart</Description>
</WebPart>
XML schema differences aside, there are essentially two changes. First, the xmlns is https://schemas.microsoft.com/WebPart/v2 instead of https://schemas.microsoft.com/WebPart/v3 indicating our move to an older format, and second, we need the assembly's public token. To get the public token, use the strong name tool with the -T parameter (sn.exe -T), or use Kirk Evans' cool trick using Visual Studio External Tools.
Alternatively, you can use the .dwp that you exported at the beginning of this exercise. Follow the steps above to create a new XML above and copy the contents of the original .dwp into your new one. Then make the following changes:
- In the WebPart root element, remove all but the xmlns attribute.
- Set the Assembly name to $SharePoint.Project.AssemblyFullName$ (you can copy this from the .webpart file)
- Set the Assembly version to your assembly's version. This is usually 1.0.0.0, but you can find it in AssemblyInfo.cs in your project.
- Replace the PublicKeyToken as described above.
- Replace the TypeName with the type name provided in your .webpart file.
Deploy
Next, we have to ensure the .dwp file is deployed with the web part. Click on the file in Solution Explorer and change its Deployment Type property from NoDeployment to ElementFile. You can now safely delete the .webpart file. Your web part folder should now look like this:
Finally, edit Elements.xml and replace both instances of .webpart with .dwp in the Elements/Module/File element. Build and deploy your project and add your web part to a SharePoint page. You should see the default search box:
Conclusion
The web part you just added to your test page may not look exactly like the original. If you created your .dwp from scratch, you will have ignored all the other properties that had been set in the .dwp for the base class. If you modified the original .dwp, you will have retained the other parameters that defined the web part's default configuration.
You are now ready to build your derived search box.
Comments
Anonymous
April 12, 2011
Great Post Man!!!Anonymous
April 20, 2011
Hey Steven, thanks for the nice post. Quick tip: if you want your custom search web part to look the same, just copy the properties that are set in the .dwp you exported in the beginning and paste them in your custom web part's .dwp.Anonymous
June 24, 2011
Frank, great point! Thank you for sharing. I just tested this too. You can copy the exported .dwp rather than build it from scratch, but you have to make the following 5 changes:
- Remove all but the xmlns attribute from the <WebPart> element
- Set the Assembly name to $SharePoint.Project.AssemblyFullName$
- Set the assembly version
- Replace the Public Key Token
- Replace the TypeName with the fully qualified type name of your new web part. I'll modify the post to reflect this.
Anonymous
October 13, 2011
SharePoint 2010: extending existing web-partsAnonymous
December 01, 2011
I've followed all the steps ..and have successfully deployed the web part ,but i couldn't able to see it on Web part gallery ,hence cannot add it to my page ..i am using VS2010 and SP 2010 .. Pls. let me know what could be the problem ..Anonymous
December 13, 2011
By default your web part is deployed in the "Custom" group in the web part gallery, so check there first. If you want to put it in a different group, edit Elements.xml (the feature manifest file). Under Elements/Module/File you will find a "Property" element with Name="Group". The value for this element is the web part gallery group name it gets deployed to. Change this to your desired group name, save and redeploy the web part. You should now find it in the group you specified.Anonymous
February 29, 2012
The comment has been removedAnonymous
October 30, 2012
Good Article....Anonymous
September 01, 2014
Hello Mate, I followed your steps but I am getting following exception: The base class or interface 'Microsoft.SharePoint.WebPartPages.WebPart' in assembly 'Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,PublicKeyToken=71e9bce111e9429c' referenced by type 'Microsoft.SharePoint.Portal.WebControls.WebPartLoc' could not be resolved. Do you know how to resolve this?? Thanks in Advance