Extending SharePoint Web Part

Hello!

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:

Or

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 HristoYankov). 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 URLreturn 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 HristoYankov{[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 changesreturn url.Replace("#current_date#", DateTime.Now.ToShortDateString());}else{// We are in edit mode, return URL as isreturn url;}}

I will be checking this later. As usual, you can get the full source code here.

But basically that’s it. With minimum amount of code and effort, we have extended the functionality of an already existing web part, to something that serves our concrete needs.

Hope this was helpful!

SharePoint Solution Hello World Tutorial

Hi,

In this post, I will explain to you how to create your first SharePoint 2007 ASP.NET application. We will cover what tools you would need and what are the steps to creating a SharePoint Hello World app! I will keep the article short and clear on the necessary steps to be followed.


First, let’s start with the tools. You will need Visual Studio 2008 SP1 (preferably) this freely available plugin for it Visual Studio 2008 extensions for Windows SharePoint Services 3.0. It is a toolset for developing custom SharePoint applications: Visual Studio project templates for Web Parts, site definitions, and list definitions; and a stand-alone utility program, the SharePoint Solution Generator.

We assume that you have setup and you do have available a SharePoint site, on which we will be deploying our solution.

So, start your Visual Studio 2008. From the menu choose to start a new Project.

Visual Studio will show this window. Select GAC and proceed.

Your Solution Explorer would look like this, initially:

We need to create a couple of folders. Recreate the folder structure described in the screenshot below:

Right click on HelloSharePointWorld and select add new item. Select text file, but name it “Hello.aspx”

Put the following content in your newly created ASPX page.

<%@ Page Language="c#"Inherits="Hello, SharePointHelloWorld, Version=1.0.0.0,Culture=neutral, PublicKeyToken=3cf44204a7ad1f1e"MasterPageFile="~/_layouts/application.master"%>

<asp:Content ID="Content1"ContentPlaceHolderID="PlaceHolderMain"runat="server"><asp:Label ID="lblLabel1" runat="server" Text="Hello World!"></asp:Label></asp:Content>

Note the PublicKeyToken value. It will be changed later. Now, create a new class in the App_Code folder. Name it Hello.aspx.cs. Your directory structure should look like:

The content of your Hello.aspx.cs should read:

using System;using Microsoft.SharePoint.WebControls;

public partial class Hello : LayoutsPageBase{ protected void Page_Load(object sender, EventArgs e) { }}

Right click on your project, select Properties from the menu. Go to the Debug tab and set the hostname and port number of the SharePoint site where you want your project to be deployed.

Then save.

Now, right click on your project in Solution Explorer and rebuild it. Then right click on it and Deploy.

Now, open Windows Explorer and navigate to C:\WINDOWS\assembly. You should see an assembly called SharePointHelloWorld there. Right click it and select Properties.

Copy the Public Key Token (highlighted, note that it would be different for you) and click Cancel button. Now go back to your ASPX page in the project and replace the incorrect Public Key Token with the one you just copied.

Redeploy your application. Start Internet Explorer and navigate to http://%5Bserver name]:[port]/_layouts/HelloSharePointWorld/Hello.aspx

You should see something similar to:

Congratulations, you have created your first SharePoint solution. If you start the Central Admin for SharePoint and go to Operations -> Solution Management you should see a solution named sharepointhelloworld.wsp.

Let’s add one more modification. Open the Hello.aspx.cs file and change it to:

using System;using Microsoft.SharePoint.WebControls;using System.Web.UI.WebControls;

public partial class Hello : LayoutsPageBase{ protected Label lblLabel1;

 protected void Page_Load(object sender, EventArgs e) {     lblLabel1.Text = "Hello world! Time is: " +     DateTime.Now.ToString(); }}

By that, we utilize the code behind to output data on the screen. Rebuild, redeploy and refresh the page.

This is a good starting point for further learning by experimenting and example.

Of course, the full code for this project can be found here.

The right way to SPWeb.EnsureUser in SharePoint

At some point of time you may need to call (SPWeb).EnsureUser from your custom SharePoint web application. But this method can not be called by everyone, as it requires some high level permissions. You may also get an error similar to this one:


Your solution is to wrap the EnsureUser within RunWithElevatedPrivileges call. However, there is a big catch. If you use instances of SPSite or SPWeb, obtained prior to the RunWithElevatedPrivileges block, it won’t work as expected because they are already associated to a non-elevated security context.

To illustrate it with code, here is WRONG usage of RunWithElevatedPrivileges:
SPWeb web = [… somehow obtained here…];

SPSecurity.RunWithElevatedPrivileges(delegate()
{
// NOTE: Wrong, do not use
SPUser someUser = web.EnsureUser(web.CurrentUser.LoginName);
});

And here is a CORRECT one:
SPWeb web = [… somehow obtained here…];

SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite elevatedSite = new SPSite(web.Site.ID))
{
SPWeb elevatedWeb = elevatedSite.OpenWeb(web.ID);
SPUser someUser = elevatedWeb.EnsureUser(web.CurrentUser.LoginName);
}
});

Basically we used the IDs of the Web and Site objects, obtained prior to the elevated block, and used them to create Site and Web object within the elevated context.

Sample SharePoint project localization Part 1 of 2

Hello,

This is a step-by-step tutorial on how to create a localized SharePoint custom web application. In this first part, we will discuss the creation of the sample web application itself, while the second one, will emphasize on the localization.

Prerequisite is a Visual Studio 2008 with WSS extensions 1.3. You can also work with Visual Studio 2005, but you will have to do part of the deployment manually.

1. Start Visual Studio and create new project of type SharePoint.

I entered ‘SPLocalization’ as name for the project.

2. Select “Full Trust”

Note: Check debug tab of Project Setting to ensure it contain correct path to your SharePoint server.

3. Add new item to our project

4. Select ‘Template’ element in SharePoint section. Change file name to ‘LocalizedPage.aspx’

— @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in } –>

5. Now you should see project structure like this:

6. Create subfolder LAYOUTS under Template folder

7. Create subfolder SPLocalization under LAYOURS folder

8. Move LocalizedPage.aspx to SPLocalization folder (I use drag and drop the file). Now you should have the following structure:

9. Now let’s create a class that extends SharePoint layout pages. Add new class to your project.

10. Name it ‘LocalizedPage.aspx.cs’ and click “Add” button

<!– @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in 11. Now few other steps …

First add references to SharePoint and SharePoint.WebControls

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

Secondly make your class public, partial and derived from LayoutsPageBase

You should see something like this:

Now, since we have chosen GAC deployment model, we need to deploy our solution to Global Assembly and determine Public Key.

12. In Visual Studio Menu, Selection, Build -> Quick Deploy Solution -> Copy Binary(s)

This will compile our SharePoint project into DLL and deploy it to GAC. After deployment Output window will show that Deployment was successful:

13. Let’s go to Windows Assembly folder and find our library

If you open Properties of our assembly, you will be able to copy its public key token. In my case it was 7a1fde53a908a4fe.

We will need Public Key Token for our aspx.page.

Now, let’s return to our ASPX page.

14. Remove default text and add Page registration tag

<%@Page Language=”C#” MasterPageFile=”~/_layouts/application.master” Inherits=”{ClassName}, {Assembly}, Version=1.0.0.0, Culture=neutral, PublicKeyToken={PublicKeyToken}” %>

Now let’s replace {ClassName} with SPLocalization.LocalizedPage {Assembly} with SPLocalization {PublicKeyToken} with Public Key Token we obtained from GAC.

Now you should see something like this:

Now let’s add some content to the page and test if everything works.

15. Add ASP tag Content with ContentPlaceHolderID equals to PlaceHolderMain. Here is complete code

<asp:Content ID=”Main” ContentPlaceHolderID=”PlaceHolderMain” runat=”server”>

Test message

<!–asp:Content>

Your Localized.aspx page should look like this:

<%@Page Language=”C#” MasterPageFile=”~/_layouts/application.master” Inherits=”SPLocalization.LocalizedPage, SPLocalization, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7a1fde53a908a4fe”%>

<asp:Content ID=”Main” ContentPlaceHolderID=”PlaceHolderMain” runat=”server”>

Test message

<!–asp:Content>

16. Let’s make a full deploy. Visual Studio menu Build -> Deploy Solution.

After deployment is completed, Output window will show that Deploy was successful.

17. Now let’s go and check manually if LocalizedPage.aspx was deployed.

Browse to 12 directory (by default it is “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12”) then browse to TEMPLATE, then to LAYOUTS, then to SPLocalization. You should see our LozalizedPage.aspx was successfully deployed.

Now let’s try to access this page through SharePoint

18. Open SharePoint url of your site with prefix “_layouts/SPLocalization/LocalizedPage.aspx”.

In my case, it is “http://itech-vm-spdev/_layouts/SPLocalization/LocalizedPage.aspx&#8221;

When page is loaded you should see empty area but with our magic text: Test message

Now, let’s add SPLinkButton SharePoint control

19. Change your ASPX page to include Register of Microsoft.SharePoint assembly and replace static text with SPLinkButton control.

Your ASPX page should look like this:

<%@Page Language=”C#” MasterPageFile=”~/_layouts/application.master” Inherits=”SPLocalization.LocalizedPage, SPLocalization, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7a1fde53a908a4fe”%>

<%@Register Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” Namespace=”Microsoft.SharePoint.WebControls” TagPrefix=”cc1″ %>

<asp:Content ID=”Main” ContentPlaceHolderID=”PlaceHolderMain” runat=”server”>

<cc1:SPLinkButton Text=”” runat=”server” ID=”myLink” />

<!–asp:Content>

20. Update your LocalizedPage class to include myLink definition. We will also assign Text value in OnLoad method. You class should look like this:

public partial class LocalizedPage : LayoutsPageBase

{

protected SPLinkButton myLink;

protected override void OnLoad(EventArgs e)

{

myLink.Text =”Our test link”;

}

}

21. Let’s do full deploy again

22. Once it is successfully deployed. Open LocalizedPage in the browser again. You should see that now you have a link on the page. This link is provided by SharePoint SPLinkButton control.

In the next article, we will discuss localization of the sample application we created…