How to use the SharePoint Web Controls

How to use the SharePoint Web Controls

SharePoint brings its own controls, which can be used to display list items. In this article I want to show you how to use them in a Webpart. It took me a while to figure this out, because the documentation is kind of incomplete L

OK. Lets start. First lets find out which SharePoint Web Control belongs to which data type in SharePoint.

 

 

 

 

 

SharePoint Web Control

SharePoint data type

SharePoint Web Control

Single line of text

TextField

Multiple lines of text

 

PlainText

NoteField

Rich Text

RichTextField

Enhanced Rich Text

RichTextField

Choice

 

Dropdown

DropDownChoiceField

Radio Button

RadioButtonChoiceField

Number

NumberField

Currency

CurrencyField

Date and Time

DateTimeField

Lookup

 

Single Item

LookupField

Multiple Items

MultipleLookupField

Yes/No

BooleanField

Person or Group

UserField

Hyperlink or Picture

UrlField

Calculated

UrlField

Business data

 

How do we find which control belongs to the data type? We can simply look up this information on each field:

string siteUrl = "http://sharepoint";
string webUrl = "spscontrols";

using (SPSite site = new SPSite(siteUrl))

{

using (SPWeb web = site.AllWebs[webUrl])

{

SPList list = web.Lists["ControlTest"];

foreach (SPField field in list.Fields)

{

Console.WriteLine(field.Title + " – " + field.FieldRenderingControl);

}

}
}

SPControlMode

You can the controls in different Control Modes:

  • SPControlMode.Edit behaves like in an editform page of a list
  • SPControlMode.Display shows the data without the ability to change the values

Use the Controls

So how do we use these controls? The answer to this question is simple: Just use them like "normal" System.Web Controls.

RichTextField rtf = new RichTextField();
rtf.ID = "MultilineRichText";
rtf.ListId = list.ID;
rtf.ItemId = item.ID;
rtf.FieldName = "MultilineRichText";
rtf.ControlMode = SPControlMode.Edit;
this.Controls.Add(rtf);

In this case the RichTextField shows the content from the "MultilineRichText" field from our list, and our listitem in the Editmode. ID and FieldName are the Displayname from our field. You have to set the List, Item and FieldName for the Control, because usually the SharePoint Controls will use the SPContext content (remember: the controls are used in the editform, newform.. pages of every SharePoint List).

With some lines of code, you can display all fields e.g. from the DefaultView of a SharePoint List:

Table table = new Table();
TableRow row;
TableCell cell;
for (int i = 0; i < list.DefaultView.ViewFields.Count; i++)
{

string fieldName = list.DefaultView.ViewFields[i];
SPField field = list.Fields.GetField(fieldName);

row = new TableRow();
cell = new TableCell();
cell.Text = field.Title;
row.Cells.Add(cell);

cell = new TableCell();

// Add a control from RH.SharePoint.SharePointWebControls
Control cntrl = SharePointWebControls.GetSharePointControls(field, list, item, SPControlMode.Display);
// if the control is null (because it can not be rendered with a SharePoint Control) return
if (cntrl == null) continue;

cell.Controls.Add(cntrl);
row.Cells.Add(cell);

cell = new TableCell();
cell.Controls.Add(SharePointWebControls.GetSharePointControls(field, list, item, SPControlMode.Edit));
row.Controls.Add(cell);
table.Rows.Add(row);

}

this.Controls.Add(table);

Use a generic control

Instead of finding a specific control for each SPField, you can use the BaseFieldControl. The advantage is, that it doesn’t matter which field you want to render. The right control will be used.

 
I have updated my class to use the generic instead of finding the matching Webcontrol. This approach makes it easier to use MOSS controls. You don’t have to distinct between WSS and MOSS controls any more.

You can Download the RH.SharePoint.SharePointWebControls class here.

Update:

I updated my SharePointWebControls.

Update 21. Apr 2008:

I updated my SharePointWebControls. This version includes a seperate file, which handels publishing controls from the Microsoft Office SharePoint Server 2007.

Update 19. Jan 2009:

SharePoint Web Controls to access remote content

Update 22. Feb 2009:

The class not uses a generic control instead of a control for each field type.

Write a SPFieldUser

If you have a list which contains a SPFieldUser field (with multiple selection), you can add users too it with the following code:

using (SPSite site = new
SPSite("http://site"))

{

using (SPWeb web = site.AllWebs["Web"])

    {

    SPList list = web.Lists["List"];

    SPListItem item = list.Items[0];

    SPFieldUserValueCollection values = (SPFieldUserValueCollection)item["Users"];

    SPUserCollection users = web.AllUsers;

    foreach (SPUser user in users)

    {

        values.Add(new
SPFieldUserValue(web, user.ID, user.Name));

    }

    item["Users"] = values;

    item.Update();

    }

}

In this example the list "List" would contain a field with the name "Users", which takes users. All web users are added to the field "Users" of the first list item, which is then updated.

Ajax Webpart displays Webservice data

In this post I want to show how to create an Ajax Webpart, which receives its data from a Webservice – and until the data arrived – shows a status bar.

As base for the Webpart, I took the one from Mark Collins and his great article http://sharethispoint.com/archive/2006/11/15/Build-web-parts-with-ajax.aspx.

The approach is to render the Webpart with only a <DIV>, and let the client – after it finishes querying the Webservice – fill the data into the <DIV> previously created.

The original version from Mark Collins comes without server side controls. I created the <DIV> as a HTMLGenericControl, because I wanted to have more control over it (and I was curious if it worked).

The basic stays the same. Long running operations are moved from your normal Webpart to the RaiseCallbackEvent method.

public
string GetCallbackResult()

{


return
this._AjaxData;

}

 

public
void RaiseCallbackEvent(string eventArgument)

{


this._AjaxData = CalculateContent();

}

The content returned by the CalculateContent Method is a simple string, which the clients renders later into the <DIV> element.

string CalculateContent()

{


string returnString = string.Empty;

 


try

{


TextWriter tw = new
StringWriter();


HtmlTextWriter _TxtWriter = new
HtmlTextWriter(tw);

 

_Grid = new
SPGridView();

_Grid.DataSource = GetGridDataSource();

 


// catch if the grid datasource is empty


if (_DS == null)

{


return
"<IMG src=\"/_layouts/images/BROKENLINK.GIF\" border=\"0\"/> no data received";

}


_Grid.DataBind();

 

_Grid.RenderControl(_TxtWriter);

returnString = _TxtWriter.InnerWriter.ToString();

}


catch (Exception ex)

{

_ErrorText += "Error in CalculateContent:\r\n:" + ex.ToString() + "\r\n";

returnString = _ErrorText;

}

 


return returnString;

}

This approach has a big disadvantage. You cannot use sorting, paging and filtering in the SPGridView, because it is created on the client side. You can use grouping, though. So what can we do about sorting and paging?

  • Sorting can be realized with a Webpart property, which takes the sort field an order, and sorts the underlying DataSet/DataView.

private
if (!String.IsNullOrEmpty(_SortString))

{


string[] sortArray = _SortString.Split(‘;’);


if (sortArray.Length == 2)

{

SortExpression = sortArray[0];

SortDirection = sortArray[1];


if (DataSetContainsField(_DS, SortExpression))

{

_DS.Tables[0].DefaultView.Sort = SortExpression + " " + SortDirection;

}

}

}

  • Filtering is also realized with a Webpart property, and modifying the DataSet/DataView

if (!String.IsNullOrEmpty(_FilterString) && _FilterString.Contains("="))

{


string filterColumnName = _FilterString.Substring(0, _FilterString.IndexOf(‘=’));

 


// catch typos in the filter


if (DataSetContainsField(_DS, filterColumnName))

{

_DS.Tables[0].DefaultView.RowFilter = _FilterString;

}

}

  • Paging: As soon, as I find a better solution, I will tell you about it J

Download the code here.

Webpart Development

Visual Studio Extensions

If you want to write your own Webpart, you can start from scratch with a Class Library, or use the templates from http://www.microsoft.com/downloads/details.aspx?FamilyID=19f21e5e-b715-4f0c-b959-8c6dcbdc1057&DisplayLang=en

The downside of this VS templates is, that they can only be used on a computer, which has SharePoint installed, and you cannot open a project created with the VS templates with a VS on which the templates are not installed.

Server side controls

Ishai Sagi wrote a great article about Webpart development. His article is about server side controls and data binding in Webparts.

Here is the link to his great article: http://feeds.feedburner.com/~r/sharepointmvpblogs/~3/106217340/server-side-controls-and-data-binding.html

Ajax

Mike Ammerlaan shows in his article how to integrate Ajax in SharePoint, and how to create a simple Ajax Webpart.

He also explains how to use UpdatePanels with Ajax, and how to disable the default SharePoint form action.

http://feeds.feedburner.com/~r/sharepointmvpblogs/~3/106217340/server-side-controls-and-data-binding.html

Ajax #2

Quote:

In this post I’m going to explain how to start using ajax in your web parts. The goal of this article is to reproduce functionality similar to the KPI and BDC web parts in MOSS 2007. If you don’t know what ajax is or the basics of how it works this article is probably not for you.

http://sharethispoint.com/archive/2006/11/15/Build-web-parts-with-ajax.aspx

Extend the simple Webpart

Now that we know how to create a simple Webpart, we want to add more functionality to it. Let us start with some Controls.

  1. Declare a Control as class variable
  2. Create it in CreateChildControls
  3. Modify the Control in OnPreRender
  4. Render the Control with its content

Declare a Control

public
class
simpleWebpart:WebPart

{

private
HtmlGenericControl _MyDiv;

CreateChildControls

This method creates the control. After the creation, we will be able to access the control from elsewhere, to modify its properties or its content.

protected
override
void CreateChildControls()

{

base.CreateChildControls();

 

// Create a new instance, and add it to the Controls

_MyDiv = new
HtmlGenericControl("DIV");

Controls.Add(_MyDiv);

}

Modify the Control

After the control exists, we can modify it.

protected
override
void OnPreRender(EventArgs e)

{

    base.OnPreRender(e);

 

_MyDiv.Attributes.Add("style", "padding: 20px; margin: 20px; border-style: groove; background-color: #FFFFFF;");

_MyDiv.InnerHtml = "I like SharePoint";

}

Rendering

Finally we render our controls, so that we actually see what we created. If we forget to do so, the controls will be generated, but not visible.

protected
override
void Render(HtmlTextWriter writer)

{


// Determines whether the server control contains child controls.


// If it does not, it creates child controls.

EnsureChildControls();

 


// Renders the ChildControls

RenderChildren(writer);

}

Deploy and Debug a Webpart to your SharePoint Server

To deploy a Webpart to a SharePoint Installation, complete the 3 steps beneath:

  1. Copy the dll from your Webpart to the bin folder of a webapplication
  2. Register the dll in the web.config as safe
  3. Add the Webpart to the Webpartgallery of a sitecollection
  4. Debug the Webpart

Copy the dll from your Webpart to the bin folder of a webapplication

Copy your dll to the bin folder of your IIS virtual server directory. In my case this is "C:\Inetpub\wwwroot\wss\VirtualDirectories\45079\bin".

If you don’t know where this directory might be, look it up in the IIS Manager.

Register the dll in the web.config

Open the web.config (e.g. "C:\Inetpub\wwwroot\wss\VirtualDirectories\45079\web.config"). Find the <SafeControls> section, and add a line like:

<SafeControl
Assembly="simple Webpart HOWTO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2e6fe95c9937e6f4"
Namespace="simple_Webpart_HOWTO"
TypeName="*"
Safe="True" />

The Assembly Name and the Namespace can be found in the properties of your project:

Add the Webpart to the Webpartgallery

Go to the Webpartgallery from your sitecollection, and add the new Webpart to your Webpartgallery.

Now you are done J You can add the new Webpart to every site in your sitecollection.

Debug the Webpart

To be able to debug a Webpart, you have to copy the dll (which was compiled in debug mode) and the pdb to the bin folder of your virtual server.

The easiest way is to set the output path for your debug configuration in the VS to the bin folder (step one from this post).

  1. Set the output path

  1. Build your Webpart
  2. Attach the VS to the Application Pool which the SharePoint site uses
    If you are unsure which w3wp you should attach the VS to, you can look it up in the IIS Manager. You can find the user in the application settings from your virtual server.

 

 

 

 

  1. Set a breakpoint and reload the site in your browser

Caution:

  • Every time you deploy your Webpart, the application pool will recycle. So deploy with care, or – better – use a testsystem to develop and test your webparts.
  • While your breakpoint is active, the whole application pool will stop executing requests to every website, which uses that application pool.

Create a simple Webpart HOWTO

In this blog post, I want to show you how to create a simple Webpart. All you need is a Visual Studio 2005 (e.g. the express version) and of course SharePoint.

  1. Start your VS and create a new "Class Library"
  2. Add a reference to the Microsoft.SharePoint.dll. We will create a SharePoint Webpart, to be able to add Properties.
  3. To display some text, override the render method. You have to create a reference to the Microsoft.Web.dll, and type using System.Web.UI;

namespace simple_Webpart_HOWTO

{

public class Class1:WebPart

{

protected override void Render(HtmlTextWriter writer)

{

writer.Write("I like SharePoint.");

}

}

}

  1. (optional) Rename Class1 to some better name like "simpleWebpart". In the solution Explorer you can rename Class1.dll to simpleWebpart.dll
  2. Add [assembly: AllowPartiallyTrustedCallers()] to the AssemblyInfo.cs
  3. Next, we will create a Key, to sign our Assembly and give it a strong name. Open the "Visual Studio 2005 Command Prompt" from the Startmenu.
    sn -k 1024 c:\temp\keypair.snk
  4. Add the created Keypair to your project, and configure it to be signed

    After you build your project, you can extract your public key token with:
    sn -T "C:\PathToYourProject\bin\debug\simple Webpart HOWTO.dll"
    In my case the token is 2e6fe95c9937e6f4

Caution:

  • ALWAYS put a try/catch block around your code, if it might generate an error. If you don’t, the whole page will display an error, instead of just your Webpart.

catch (Exception ex)

{

HtmlGenericControl errorControl = new HtmlGenericControl("DIV");

errorControl.Attributes.Add("style", "padding: 20px; margin: 20px; border-style: groove; background-color: #FFFFFF;");

errorControl.InnerHtml = "<IMG src=\"/_layouts/images/error16by16.gif\" border=\"0\"/>" + ex.ToString();

Controls.Add(errorControl);

}

You can download the solution here.

Reporting Services and XML Datasource

Querying a XML Datasource

Query:

<Query>

    <SoapAction>http://ns.tld/MethodName</SoapAction>

    <Method
Namespace="http://ns.tld/"
Name="

MethodName" />

    <ElementPath
IgnoreNamespaces="True">*</ElementPath>

</Query>

Passing Parameters

You only have to define your parameters in the parameter tab of your dataset. They are passed automatically to the Webservice Method. If you want to define your parameter yourself and not use a Reporting Services Parameter, just type

<Query>

    <SoapAction>http://ns.tld/MethodName</SoapAction>

    <Method
Namespace="http://ns.tld/"
Name=" MethodName">

        <Parameter
Name="ParamName">

            <DefaultValue>ParamValue</DefaultValue>

        </Parameter>

    </Method>

    <ElementPath
IgnoreNamespaces="True">*</ElementPath>

</Query>

Wiki mit Bildern Update

Falls bei der Benutzung des Webparts ein Fehler wie:

Fehler bei der Anforderung des Berechtigungstyps Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.

auftritt, muss der Trustlevel in der web.config auf Full gesetzt werden.

<trust level="Full" originUrl="" />

Zum vollständigen Beitrag: http://www.hezser.de

Update 23. Apr 2008:

Ich habe eine neue Version bereitgestellt.

Sending Email from SharePoint

You can configure a task list, to send an email if you assign a task to somebody. This works fine if this somebody has an internal email address.

If you happen to have an account inside the environment of the SharePoint Server, and configure it to have an external email address, sending an email to this account might fail. In the SharePoint Logs there is an entry:

03/12/2007    14:40:42.29    OWSTIMER.EXE (0x059C)    0x14E8    Windows SharePoint Services    E-Mail    8gsf    High    #160009: Die E-Mail-Adresse ‘somebody@somewhere.tld’ ist unbekannt. (something like: the email address ‘somebody@somewhere.tld’ is unknown)

(if not, adjust your logging for email events)

To be able to send emails to recipients outside your environment, you have to grant your SharePoint Server the right to send emails in the virtual SMTP Server of your Exchange Server.

C#, fast assignment

Here is a short way to declare a variable and set a value according to a condition:

bool var = (something == true) ? true : false;

The long way would be:

bool var;
if (something == true)
{
    var = true;
}
else
{
    var = false;
}

I like the short way. You have to decide for yourself

Update:

This was a bad example. If you want to set a bool, just type:

bool var = something;

Remove Server from Farm

After adding a new Server to the SharePoint farm, I removed the old one.

The central administration page was not accessible. It said "error 500" in the browser. By changing the admin port via "stsadm -o setadminport -port 12345" and back to the original port, I was able to regain access to the central administration page.

Testlink to Yvonne for EBE Tracking Test: http://yvonneharryman.wordpress.com/2009/06/28/sharepoint-beacon-is-the-new-home-for-my-blog-regarding-sharepoint/

Remove Server from Farm

After adding a new Server to the SharePoint farm, I removed the old one.

The central administration page was not accessible. It only said "error 500" in the browser. By changing the admin port via "stsadm -o setadminport -port 12345" and back to the original port, I was able to regain access to the central administration page.

Reporting on SharePoint Lists

You can do Reporting on SharePoint Lists with SQL Server Reporting Services 2005 quite easy.

  1. Configure the Datasource with integrated Security
  2. Define a query like

    <Query>
    <SoapAction>http://schemas.microsoft.com/sharepoint/soap/GetListItems</SoapAction>
    <Method Namespace="http://schemas.microsoft.com/sharepoint/soap/" Name="GetListItems">
    <Parameters>
    <Parameter Name="listName">
    <DefaultValue>SharePoint List Name</DefaultValue>
    </Parameter>
    </Parameters>
    </Method>
    <ElementPath IgnoreNamespaces="True">*</ElementPath>
    </Query>

  3. Hit the "Field Refresh" Button to get the Field from your SharePoint List
  4. Drag your Fields in the Report
  5. Use the Code to eliminate "ID;#" and "<div>","</div>" from your Fields

    Use "=Code.CuttOff(Fields!ows_LinkTitle.Value)" in your Report to display your Fields

Webpart, Properties and default value

If you write a Webpart with custom properties, you have to take care of the default value.

[WebBrowsable(true),
DefaultValue("value"),
Personalizable(true),
WebDisplayName("some property"),
WebDescription("Description of the property")]
public
string PropertyName
{
get { return _ PropertyName; }
set { _ PropertyName = value; }
}

Please do not specify a default value, which you might actually use. The default property value will not be saved, if you choose to configure it with the default value!

Wiki mit Bildern

Bei einem Blog Eintrag kann man Bilder mit an den Eintrag anfügen. Dies ist jedoch bei der Wiki Vorlage der Windows SharePoint Services V3 nicht möglich.

Um dieses Manko zu beseitigen, habe ich ein Webpart geschrieben. Dieses wird in die editform.aspx der Wiki List eingebaut. Danach kann man bequem über die Pflegemaske der Wiki Einträge Bilder an einen Wiki Beitrag anfügen. Die Bilder werden automatisch in eine Bildbibliothek hochgeladen.

Installation:

  1. Kopieren der Assembly in das bin Verzeichnis des virtuellen Servers
  2. Registrieren des Webparts in der web.config
    <SafeControl Assembly="WikiWebpart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b17a955c3eada4c1" Namespace="WikiWebpart" TypeName="*" Safe="True" />
  3. Hinzufügen des Webparts auf der editform.aspx (mit dem SharePoint Designer)
  4. Erstellen einer Bildbibliothek in der Wiki Site
    Wenn Sie mehrere Bildbibliotheken auf der Wiki Site haben, kann in den Webpart Eigenschaften eine Bildbibliothek eingetragen werden.

Hinweis:
Wenn ein Bild angefügt wird, wird der Beitrag nicht gespeichert. Deshalb immer erst ein Bild hochladen, und dann den Beitrag bearbeiten!

Download: WikiWebpart

Update:

Falls bei der Benutzung des Webparts ein Fehler wie:

Fehler bei der Anforderung des Berechtigungstyps Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.

auftritt, muss der Trustlevel in der web.config auf Full gesetzt werden.

<trust level="Full" originUrl="" />

Update:
Ich habe eine neue Version des Webparts veröffentlicht. Siehe hier.

Error 6483

Auf einem Server habe im Ereignisprotokoll immer wieder eine Meldung mit der ID 6483 gefunden:

Quelle: Office SharePoint Server Kategorie: Gemeinsamte Dienste Ereigniskennung: 6483

Quelle: Office SharePoint Server
Kategorie: Gemeinsamte Dienste
Ereigniskennung: 6483

Zur Behebung des Problems habe ich versucht eine Reparaturinstallation durchzuführen. Jedoch ist diese mit Fehlermeldungen abgebrochen:

Die Konfiguration von Microsoft Office SharePoint Server 2007 wurde nicht erfolgreich abgeschlossen. Für das Produkt Microsoft SharePoint Services 3.0 1031 Lang Pack wurde kein Installationspaket gefunden.

Also habe ich nacheinander alle Pakete nachinstalliert, die während der Reparatur angemeckert wurden. Im Endeffekt waren dass alle msi Pakete auf der Microsoft Office SharePoint Server 2007 CD, außer den uninstall Paketen.

Im Anschluss konnte ich jedoch die Reparatur erfolgreich durchführen. Nach dem obligatorischen Neustart musst ich nur noch den Konfigurationswizzard durchlaufen, und das System lief wieder wie gewünscht.

Upgrade eines SPS 2003 Portals auf MOSS 2007

In den letzten Tagen habe ich versucht ein SharePoint Portal Server 2003 Portal auf Microsoft Office SharePoint Server 2007 zu aktualisieren. Hierbei bin ich über einige Probleme gestolpert.

Folgende Upgradeversuche habe ich getestet:

  1. Anhängen der Inhaltsdatenbanken an eine neue Microsoft Office SharePoint Server 2007 Webanwendung
  2. Inplace Upgrade des gesamten Servers
  3. Gradual Upgrade

Leider hatte ich bei den ersten 2 Versuchen eine Fehlermeldung erhalten:
[SPManager] [ERROR] [04.02.2007 11:39:28]: ReflexiveUpgrade [SPWebServiceInstance Parent=SPServer Name=SHAREMIG] failed.
[SPManager] [ERROR] [04.02.2007 11:39:28]: Die Eingabezeichenfolge hat das falsche Format.
[SPManager] [ERROR] [04.02.2007 11:39:28]: bei System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)…

Oder:
"Die Eingabezeichenfolge hat das falsche Format" wenn ich die Datenbank mittels stsadm anfügen wollte.

Zu dieser Fehlermeldung habe ich jedoch keine weitere Erklärung finden können.

Jedoch habe ich im Upgrade.log des dritten Versuchs eine aussagekräftigere Fehlermeldung erhalten:

[SiteSequence] [ERROR] [04.02.2007 17:53:13]: Der Gruppenname ist leer, oder Sie verwenden eines oder mehrere der folgenden ungültigen Zeichen: " / \ [ ] : | < > + = ; , ? * ‘ @

[SiteSequence] [ERROR] [04.02.2007 17:53:13]: bei Microsoft.SharePoint.Library.SPRequestInternalClass.AddRoleDef(String bstrUrl, String bstrName, String bstrDescription, Boolean bHidden, Int32 lRoleOrder, UInt64 iPermMask, Byte iType, Int32 lRoleDefID)

bei Microsoft.SharePoint.Library.SPRequest.AddRoleDef(String bstrUrl, String bstrName, String bstrDescription, Boolean bHidden, Int32 lRoleOrder, UInt64 iPermMask, Byte iType, Int32 lRoleDefID)

In einigen Bereichen und Teamsites wurden Gruppen berechtigt, die ein + im Namen haben. Genau wie eine # als ersten Buchstaben eines Serviceaccounts, scheint auch ein + nicht empfehlenswert zu sein…