Friday, February 4, 2011

Extending SharePoint Web Part

SharePoint provides a lot of different out-of-the-box Web Parts. But sometimes we wish a particular web part behaved in a little different way, or have some small extra functionality. Or we may want to implement a heavily modified Web Part, based on already existing one.

Today, I will show you how to extend the functionality of an already existing web part.


We will take for example the SharePoint RSS Viewer. It loads an RSS feed and visualizes it in a web part on a SharePoint site. One of its visible properties in the UI is the Feed URL. It's a static string and doesn't allow any kind of dynamic parameters. Example:
  • You can write: http://servername/service?Zip=92692
  • But you can't: http://servername/service?Zip=#zip_of_current_location#

Or
  • You can write: http://servername/service?IP=192.168.1.5
  • But you can't: http://servername/service?IP=#current_ip#

Those placeholders in my example are fictional, but you should get the idea of a dynamic value passed as a parameter to the service.

Our goal is to override the default behavior of the Feed URL field. We want to get to a point where we actually control how the Feed URL is being interpreted. We may want to replace placeholders with actual values, or do any other kind of adjustment of the URL, based on current and dynamic conditions. So here is the plan: we create a new web part, inherit the RSS Viewer web part and extend the Feed URL property.

Let's start. Here is how the RSS View part settings look like in edit mode:


See the RSS Feed URL field? That's what we are interested in.

Ok, start Visual Studio 2008 with the VSeWSS plugin installed. From the menu, start a new SharePoint -> Web Part project.


Give it a full trust


Change your namespace to something you prefer (for example, I will change it to Sivareddy). Rename the folder 'WebPart1' to 'RSSAggregatorWebPartDynamicParam'. It will rename all classes and files for you. In the Solution Explorer, expand Properties and open AssemblyInfo.cs. Add this to the bottom:
[assembly: AllowPartiallyTrustedCallers]

and this to the top:
using System.Security;

Your Solution Explorer should look similar to:


Right click on your project, click on Properties, go to the Debug tab and set the SharePoint site URL you will be deploying to.


Open the RSSAggregatorWebPartDynamicParam.webpart file and set Title and Description to whatever you like.

Now, after your project is setup, starts the interesting part. Let's inherit the RSS View control! What you need to do is...

Add this file as a reference - C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\microsoft.sharepoint.portal.dll. This is where the RSS View class is defined.

Open your RSSAggregatorWebPartDynamicParam.cs file and change your class from this:
public class RSSAggregatorWebPartDynamicParam : System.Web.UI.WebControls.WebParts.WebPart

to that:
public class RSSAggregatorWebPartDynamicParam : RSSAggregatorWebPart

And add this statement:
using Microsoft.SharePoint.Portal.WebControls;

Basically, we no longer inherit the basic WebPart class. Instead, we now inherit the whole functionality of the RSS Viewer web part and all of its user interface!

You can also delete this function, as we are not going to do any changes there.
protected override void CreateChildControls()

So far so good. Now let's override the Feed URL property! Add this to your class:
[DefaultValue(""),
Resources("RSSWebpart_Property_FeedUrl_Text",
"RSSWebpart_ToolPart_Group",
"RSSWebpart_Property_FeedUrl_Description"),
Personalizable(PersonalizationScope.Shared),
WebBrowsable(true)]
public new string FeedUrl
{
get
{
return base.FeedUrl;
}
set
{
base.FeedUrl = value;
}
}


And add this statement:
using System.ComponentModel;

Three things to note here:
1. The FeedUrl property is the one which handles the URL which points to the RSS feed.
2. Note the attribute on top of the property. If you don't add it, it won't be visible in the UI
3. Note the 'new' keyword. This way we hide the underlying base FeedUrl property.

Ok, now we have control over the Feed URL. What we should do, is change the way FeedUrl is being returned. Change your get to look like:
get
{
return OverrideURL(base.FeedUrl);
}


And create this function:
private string OverrideURL(string url)
{
// TODO: Process the URL
return url;
}


So, in OverrideURL we can change any way we like the URL that is set in the User Interface and then return it modified. At this point, it is up to you how to utilize this capability.

For the purpose of the example, let's just look for the string #current_date# in the URL and replace it with the current date.
private string OverrideURL(string url)
{
return url.Replace("#current_date#", DateTime.Now.ToShortDateString();
}


At the end, your code should look like:
using System;
using System.Runtime.InteropServices;
using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Portal.WebControls;
using System.ComponentModel;

namespace Sivareddy
{
[Guid("03badfa9-53e4-401a-bc60-28db88b202ac")]
public class RSSAggregatorWebPartDynamicParam : RSSAggregatorWebPart
{
   public RSSAggregatorWebPartDynamicParam()
   {
   }

   [DefaultValue(""), Resources("RSSWebpart_Property_FeedUrl_Text", "RSSWebpart_ToolPart_Group", "RSSWebpart_Property_FeedUrl_Description"), Personalizable(PersonalizationScope.Shared), WebBrowsable(true)]
   public new string FeedUrl
   {
       get
       {
           return OverrideURL(base.FeedUrl);
       }
       set
       {
           base.FeedUrl = value;
       }
   }

   private string OverrideURL(string url)
   {
       return url.Replace("#current_date#", DateTime.Now.ToShortDateString());
   }
}
}

Now, right click your project and do 'Deploy'. It should add a RSSAggregatorWebPartDynamicParam assembly to your GAC. When you go to your SharePoint site and do 'Edit Page' -> 'Add Web Part'

you should be able to see your newly created web part listed in the pop up. Add it to the page. Put it in Edit Settings mode and set the Feed Url to something like:
http://servername/service/Param1=#current_date#

It will be replaced by:
http://servername/service/Param1=06/06/2009 (for example)


NOTE: I just noticed this - as soon as you set the URL which contains the 'placeholder', the web part which is still in edit mode starts showing it with a replaced value (the date). I believe that the underlying value is still http://servername/service/Param1=#current_date#. So perhaps, in the method OverrideURL we should be taking into consideration if the web part is in edit mode. And if it is - just return the original parameter that was passed. Something like:
private string OverrideURL(string url)
{
if (this.NotInEditMode)
{
// Not in edit mode, perform changes
return url.Replace("#current_date#", DateTime.Now.ToShortDateString());
}
else
{
// We are in edit mode, return URL as is
return url;
}
}

No comments:

Post a Comment