Welcome to MSDN Blogs Sign in | Join | Help

Share Points

Development on the SharePoint Platform
Writing Windows SharePoint Services Server-Side controls

Overview

This post tries to describe the process of writing a .NET server-side control for Microsoft Windows SharePoint Services

 

There are a number of ways to write add-in code for SharePoint Technologies, the most notable being web parts. 

However, these do not always help in the customisation of a site.  Sometimes, we need to be able to change the

SharePoint look'n'feel and web parts do not integrate seamlessly in an area we want to control..  If we consider that

SharePoint is an ASP.NET application, we are able to use other .NET techniques to deliver the look and customisation

we want.

 

One of those methods is via compiled controls.  Most commonly used would be user controls but we can also write

server controls

 

Mini-Navigator

In this post, I will be describing how I wrote a server control that I call a Mini-Navigator.  See below:

 

 

This is a server control written in VB.NET.  It initially outputs the logged on user information, this is because when I am sometimes testing,

it is really easy for me to forget with IE session is representing which user.  Then, it should give you the current site, the parent site to you

and the children site beneath you.  So, it renders out 1 level above and 1 level below and displays the appropriate icon for the site. 

Hovering on the site will display the sites' Title/Description information and clicking on the site will navigate the current window to it.

If you wanted to open the site in a new window, remember to hold the <Shift> key when clicking on the site.

 

In the above example, if I clicked on the site "bridport", you would get:

 

 

So that’s what the control looks like, so how can we put this into a SharePoint site?

 

Step 1 - Building the control

This is just using one of the default templates that comes with Visual Studio .NET 2003.  The control that I will be building here

will be going into the Global Assembly Cache (GAC) on my SharePoint server so I need to strongly name it.

 

So, open Visual Studio .NET 2003, then "File/New/Project".  In your language of choice, you should see a template called

"Windows Control Library".  This is the template I will be using.

 

The control uses the WSS Object Model (OM), se we need to add a reference to "Windows SharePoint Services"

 

Note: This assumes you are developing on a machine that has WSS installed already.  If

not, you will need to obtain the appropriate DLLs and add them.

 

You will need to set up your own appropriate namespace.  My code looks like:

 

MiniNavigatorSC.VB

Imports System.ComponentModel

Imports System.Web.UI

Imports Microsoft.SharePoint

Imports Microsoft.SharePoint.Utilities

Imports Microsoft.SharePoint.WebControls

 

 

<DefaultProperty("Text"), ToolboxData("<{0}:MiniNavigator runat=server></{0}:MiniNavigator>")> Public Class MiniNavigator

  Inherits System.Web.UI.WebControls.WebControl

 

  Dim _text As String

 

  <Bindable(True), Category("Appearance"), DefaultValue("")> Property [Text]() As String

    Get

      Return _text

    End Get

 

    Set(ByVal Value As String)

      _text = Value

    End Set

  End Property

 

  '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter)

    Dim oSite As SPWeb = SPControl.GetContextWeb(Context)

    Dim oSubWebs As SPWebCollection = oSite.Webs

    Dim oSubWeb As SPWeb

    Dim sOutput As String = ""

    Dim sImg As String = ""

 

    'Output the CurrentUser so that the user is aware of who they are logged in as.

    sOutput = "<table><tr><td colspan=2 class='ms-tabselected' title='Logged in as:'>"

    sOutput += oSite.CurrentUser.LoginName.ToString + "</TD></TR>"

 

    'If at a site collection, the ParentWeb object will be nothing

    If (oSite.IsRootWeb) Then

      'Site Collection level.  The parent maybe a portal

      sOutput += "<tr><td valign='top'><img src='/_layouts/images/opx16.gif' alt=''></td><td width=90% class='ms-nav a' title='This is a SharePoint Portal site'" +        oSite.PortalName + "><a href='" + oSite.PortalUrl.ToString + "'>" + oSite.PortalName.ToString + "</a></td></tr>"

    Else

      Dim sSiteName As String = ""

 

      If (oSite.ParentWeb.Name.ToString.Length <> 0) Then

        sSiteName = oSite.ParentWeb.Name.ToString

      Else

        sSiteName = Right(oSite.ParentWeb.Url.ToString, oSite.ParentWeb.Url.ToString.Length - oSite.ParentWeb.Url.ToString.LastIndexOf("/") - 1)

      End If

 

        sOutput += "<tr><td><img src='/_layouts/images/" + getGif(oSite.WebTemplate.ToString, oSite.Configuration) + ".gif' alt=''></td><td width=90% class='ms-nav a' title='Site Title: " + oSite.ParentWeb.Title.ToString + " / " + oSite.ParentWeb.Description.ToString + "'><a href='" + oSite.ParentWeb.Url.ToString + "'>" + SPEncode.HtmlDecode(sSiteName) + "</a></td></tr>"

      End If

 

      'The current site

      sOutput += "<tr><td><img src='/_layouts/images/" + getGif(oSite.WebTemplate.ToString, oSite.Configuration) + ".gif' alt=''></td><td class='ms-selectednav' width=90% title='You are here'>" + oSite.Title.ToString + "</td></tr>"

 

      'The child sites

      For Each oSubWeb In oSubWebs

        sOutput += "<tr><td valign='top'><img src='/_layouts/images/" + getGif(oSubWeb.WebTemplate.ToString, oSubWeb.Configuration) + ".gif' alt=''></td><td width=90% class='ms-nav a' title='Site Title: " + oSubWeb.Title.ToString + " / " + oSubWeb.Description.ToString + "'><a href='" + oSubWeb.Url.ToString + "'>" + oSubWeb.Name.ToString + "</a></td></tr>"

      Next oSubWeb

 

      sOutput += "</table>"

      output.Write(sOutput)

 

    End Sub

 

    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    Private Function getGif(ByVal sType As String, ByVal iConfig As Integer)

      Select Case sType

        Case "MPS"

          Return "MTGICON"

        Case Else

          Select Case iConfig

            Case 0

              'Team Site

              Return "STSICON"

            Case 1

              'Blank Site

              Return "MSCNTVWL"

            Case 2

              'Document Workspace

              Return "DOCICON"

            Case Else

              'Set as a team site

              Return "STSICON"

          End Select

 End Select

      End Function

 

End Class

 

AssemblyInfo.VB

Imports System

Imports System.Reflection

Imports System.Runtime.InteropServices

 

' General Information about an assembly is controlled through the following

' set of attributes. Change these attribute values to modify the information

' associated with an assembly.

' Review the values of the assembly attributes

 

<Assembly: AssemblyTitle("Mini-Navigator")>

<Assembly: AssemblyDescription("This is a server control that can be added to a SharePoint site to display the parent and children site information")>

<Assembly: AssemblyCompany("Bridport")>

<Assembly: AssemblyProduct("")>

<Assembly: AssemblyCopyright("")>

<Assembly: AssemblyTrademark("")>

<Assembly: CLSCompliant(True)>

 

'The following GUID is for the ID of the typelib if this project is exposed to COM

<Assembly: Guid("ED83C45C-4EBC-4a51-89AE-E95EB38C4AB1")>

 

' Version information for an assembly consists of the following four values:

'

'

Major Version

'

Minor Version

'

Build Number

'

Revision

'

' You can specify all the values or you can default the Build and Revision Numbers

' by using the '*' as shown below:

<Assembly: AssemblyVersion("1.0.0.0")>

<Assembly: AssemblyKeyFile("../../MiniNav.snk")>

 

Click here to download the project.  The project contains the files previously mentioned plus the MiniNavigatorSCCS.cs which is the C# equivalent code for all you C#'ers out there!

 

Note: you will have to add your own KeyFile using SN -K called MiniNav.SNK and located in the

project directory at the same level as the .VB files

 

Now we have the control built and it is ready to deploy to the SharePoint Server

 

So, what does the code do?

Nothing hard or tricky really, just gets the site context from:

Dim oSite As SPWeb = SPControl.GetContextWeb(Context)

 

Then this context is used to get the Current User information from the WSS OM property

oSite.CurrentUser.LoginName.ToString

 

We then just work through the object model to get the parent and children site information.

 

To get the correct icons for the workspace, we use:

oSubWeb.WebTemplate and  oSubWeb.Configuration

 

I do make an assumption here that you are using the default site definitions.  If you have modified these,

you may need to change this piece of code

 

Step 2 - Deploy the control

As I may want to use the control on any site on my SharePoint server, over a number of portals,

I copy the built DLL, MiniNavigator.DLL, to the server GAC.

 

The control sits on a WSS default page, so we have to edit the sites' default.ASPX.  There are a number of

ways to update this file using many editors such as FrontPage2003 but…  I normally edit the page by

first mapping a web folder to the site

 

 

(REALLY IMPORTANT NOTE: Make sure you keep a copy of the original DEFAULT.ASPX file before

you edit it just in case!!!!)

 

I would then drag'n'drop the default.aspx file to my desktop and open it using NotePad and add the control

reference thus:

 

The line we are interested in is:

….

<%@ Register Tagprefix="NMB" Namespace="MiniNavigator" Assembly="MiniNavigator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7dd16f83bffd70b1" %>

….

 

With the reference in, we now need to place the control at the appropriate location within the ASPX file.  As, this

control is to be displayed on the navigation area of the site, I put it as shown below:

 

 

Again, the lines I added are:

 

<TR>

  <TD style="padding-left:0px;padding-right:0px">

    <img width=1px src='/_layouts/images/blank.gif' ID='100' alt='Icon' border=0>

    <NMB:MiniNavServerControl id="NigelSC1" runat="server" /> 

  </TD>

</TR>

 

NOTE: You may find it easier to use FrontPage2003 to actually do this manipulation as it is easier to locate

the actual HTML where you want to drop the control

 

Now, save the file and drag it back to the WSS web folder where you originally dragged the file from, overwriting the

original file.  (This will create a custom version of the file and it is handled slightly differently by SharePoint from

default sites without customisation.  These files are more commonly called "one-off" or "unghosted")

 

The final part of the deployment is to update the appropriate web.config file to allow the control to

render.  So, open the web.config and add the reference for the control into the <SafeControls> section:

 

The line is

<SafeControl Assembly="MiniNavigator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7dd16f83bffd70b1"

    Namespace="MiniNavigator" TypeName="*" Safe="True" />

 

Now do an IISRESET and view the site!

Posted: Thursday, November 18, 2004 5:33 PM by NigelBridport

Comments

EROL said:

Thanks, nice EROL
# November 18, 2004 6:10 PM

Todd Spatafore said:

That's a pretty cool control and I'm using it same as you to help with testing (who am I again...), but I'm having a couple of problems with it. The first is that I don't show opx16.gif as being in my /_library/images/ folder (can't find it anywhere). The other one is probably something in my translation from VB.NET to C#, but the oSite.PortalUrl.ToString() and the oSite.PortalName.ToString() don't output anything. Great control though.
# November 18, 2004 9:28 PM

Patrick Tisseghem's Blog said:

# November 19, 2004 12:32 AM

Nigel said:

opx16.gif (The Portal representation) should be in your /_layouts/images/ directory [...\Program Files\Common Files\Microsoft Shared\web server extensions\60\template\images\]. I took the gif references from a SPS 2003 SP1 installation. Just change the reference to a 16*16 gif on your system.

I will try and post a C# version later today!
# November 19, 2004 8:22 AM

Nigel said:

The download now contains a new file:

MiniNavigatorSCCS.CS

This is the main routine converted into C#. I have done a quick test and it seems ok!

Nigel.
# November 19, 2004 10:33 AM

Omar Al Zabir Blog said:

# November 19, 2004 6:39 AM

Todd Spatafore said:

Nigel,
Thanks for posting the C# version. It's almost identical to what I have (I split the string on / and used the last element in the array instead of doing substring as that line of code got a bit long for me). I'm still having the same problems though which makes me think something is wrong with my sharepoint install. I'll try it on another test machine I have and see what's up. Thanks again.
# November 19, 2004 4:44 PM

Martin said:

Great Job Nigel! - going to check it out in depth this weekend !

-- Martin
# November 19, 2004 7:20 PM

Bob Mixon said:

Nigel,

Great run-through on how to accomplish this! Keep up the great work.

Bob Mixon
# November 20, 2004 5:32 PM

SharePoint, SharePoint and stuff said:

In der letzten Woche sind eine ganze Reihe von interessanten Artikeln zu Sharepoint erschienen:
# November 21, 2004 4:16 PM

EROL said:

Congratulation EROL
# December 3, 2004 9:07 PM

Jim Duncan said:

Thanks for the great info! Helped me create a server control for the Blog site definition I've created.

http://dev.collutions.com/blogs/sample
# December 9, 2004 2:34 AM

Outlook by the sound said:

# January 14, 2005 9:47 PM

tchmiel's blog said:

In wssV2, we had created a simple custom site definition which was based on the default STS team site

# July 29, 2007 11:16 PM

Les includes | hilpers said:

# January 22, 2009 9:36 AM
Anonymous comments are disabled
Page view tracker