Anforderung
SharePoint Kontaktlisten werden üblicherweise benutzt, um von Mitarbeitern, Kunden, Partnern etc. Kontaktinformationen zu hinterlegen. Eine solche Kontaktinformation ist z. B. die E-Mail Adresse eines Kontaktes.Möchte man nun eine E-Mail an alle Kontakte einer Kontaktliste oder eine Auswahl von Kontakten dieser Liste senden, so findet man in SharePoint keine einfache Möglichkeit, einen entsprechenden E-Mail Verteiler zu erstellen.
Da wir eine solche Funktion auch in unserem SharePoint-Web benötigen, habe ich einen einfachen Web Part implementiert, welcher einen mailto-Link aus einer SharePoint Liste mit E-Mail Adressen generiert. Zusätzlich steht ein Filterkriterium zur Verfügung, um nur bestimmte E-Mail-Adressen in den Verteiler aufzunehmen.
Damit dieser Web Part auch von einem SiteCollection-Administrator eingespielt werden kann, der keinen Zugriff auf die SharePoint Zentraladministration besitzt, habe ich diesen Web Part als Sandboxed Solution implementiert.
Wichtiger Hinweis:
Damit Sandboxed Solutions in einer Share Point Umgebung verwendet werden können, muss in der SharePoint Farm das Microsoft SharePoint Foundation Sandboxed Code Service gestartet sein. Dieses Service ist standardmäßig gestoppt. Zu finden ist dieses Service in der SharePoint Zentraladministration unter „System Settings „->“Manage Services on Server“.
Entwicklungsumgebung
Bei der Implementierung des Web Parts kam folgende Entwicklungsumgebung zum Einsatz:
– Microsoft SharePoint 2010
– Microsoft Visual Studio 2010 (C#)
– Visual Studio 2010 SharePoint Power Tools
Die Visual Studio 2010 SharePoint Power Tools stellen ein Item Template für Sandboxed Visual Webparts zur Verfügung und stellen auch sicher, dass nur SharePoint Objekte verwendet werden, die in einer Sandboxed Solution erlaubt sind. Für eine Sandboxed Solution unerlaubte Elemente führen zu einem Übersetzungfehler.
Implementierung
In Visual Studio wählt man als Projekt Template „Empty SharePoint Project“:

Nur dieses Template erlaubt im nächsten Schritt die Auswahl von „Deploy as a sandboxed solution“:
Im Solution Explorer bekommen wir nun folgenden Projektbaum:

Nach Rechtsklick auf den Root-Knoten und Auswahl von „Add“-„New item…“ können wir nun einen Sandboxed Visual Web Part zu unserem Projekt hinzufügen:
Wir benennen den Web Part als „MailToControl“ und erhalten nun folgenden Projektbaum:
Nun können wir mit der Implementierung des Web Parts beginnen:
Durch Doppelklick von MailToControl.asc öffnet sich der Web Part Designer. Ich habe hier eine CheckBoxList für den Filter, einen Button zum Aktualisieren des E-Mail-Verteiler-Links und ein HyperLink-Control für den generierten E-Mail-Verteiler hinzugefügt:
Der Filter wird später mit einem SharePoint Choice-Feld verknüpft. Der Filter zeigt alle Elemente des Choice-Feldes mit einer Checkbox an und erlaubt ein beliebiges Kombinieren dieser Elemente.
Der vom Designer generierte Code sieht folgendermaßen aus:
<p>
<asp:CheckBoxList ID=“listFilter“ runat=“server“>
</asp:CheckBoxList>
</p>
<p>
<asp:Button ID=“btnGenerateLink“ runat=“server“ Text=“E-Mail Verteiler aktualisieren“
onclick=“btnGenerateLink_Click“ />
</p>
<p>
<asp:HyperLink ID=“linkMailTo“ runat=“server“>mailto:</asp:HyperLink>
</p>
Wie man hier sieht, habe ich auch noch einen „onclick“-Eventhandler „btnGenerateLink_Click“ hinzugefügt, über den der mailto-Link aktualisiert werden kann.
Der Web Part soll später für beliebige Share Point Listen einsetzbar sein, d. h. wir benötigen eine Konfigurationsmöglichkeit des Namen der Shar Point Liste, des Namen der E-Mail Spalte und des Namen des Choice Feldes für den Filter.
Diese Konfigurationsmöglichkeiten implementieren wir in der Code-Behind Klasse unseres Web Part Controls (MailToControl.ascx.cs) als Public Properties:
[WebBrowsable(true),
Category(„Miscellaneous“),
WebDisplayName(„SharPoint list“),
DefaultValue(„“),
Personalizable(PersonalizationScope.Shared),
WebDescription(„“)]
public string listTitle { get; set; }
[WebBrowsable(true),
Category(„Miscellaneous“),
WebDisplayName(„Filter column (choice field!)“),
DefaultValue(„“),
Personalizable(PersonalizationScope.Shared),
WebDescription(„“)]
public string listFilterCol { get; set; }
[WebBrowsable(true),
Category(„Miscellaneous“),
WebDisplayName(„Email column“),
DefaultValue(„Email“),
Personalizable(PersonalizationScope.Shared),
WebDescription(„“)]
public string listEmailCol { get; set; }
Mit „Category(„Miscellaneous“)“ teilen wir dem Web Part mit, dass dieses Property in einem „Miscellaneous“-Bereich der Web Part Konfiguration editierbar ist.
Der „WebDisplayName“ wird im Label für die Property-Textbox angezeigt.
„Personalizable(PersonalizationScope.Shared)“ gibt an, dass der konfigurierte Wert für alle Anwender gelten soll.
Damit der Web Part auch für Listen ohne Choice-Feld funktioniert, kann das Property „Filter column“ in unserer Implementierung auch leer gelassen werden.
Als nächstes implementieren wir die „Page_Load“-Methode. Hier wird die CheckBoxList mit den möglichen Filterelementen initialisiert und der ungefilterte mailto-E-Mail-Verteiler-Link ausgegeben.
Die Initialisierungen dürfen natürlich nur beim initialen Laden der Seite, auf dem der Web Part eingebettet ist, erfolgen. Bei einem PostBack, also wenn man z. B. den „E-Mail Verteiler aktualisieren“-Button klickt, kümmert sich das ASP.NET Framework darum, dass die Daten nicht verloren gehen.
Fehler, die aufgrund einer falschen Konfiguration des Web Parts auftreten, werden der Einfachheit halber im HyperLink Control angezeigt.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (String.IsNullOrEmpty(listTitle)) return;
// Get current web reference from SharePoint context
SPWeb web = SPContext.Current.Web;
// Get desired SharePoint list
SPList list = null;
try
{
list = web.Lists[listTitle];
}
catch
{
linkMailTo.Text = (String.Format(„ERROR: Unknown list ‚{0}‘.“, listTitle));
return;
}
// Shall we use a filter column?
if (!String.IsNullOrEmpty(listFilterCol))
{
SPFieldChoice field = null;
try
{
field = list.Fields[listFilterCol] as SPFieldChoice;
}
catch
{
linkMailTo.Text = (String.Format(„ERROR: Unknown list column ‚{0}‘.“, listFilterCol));
return;
}
if (field == null)
{
linkMailTo.Text = (String.Format(„ERROR: List column ‚{0}‘ is not a choice field.“, listFilterCol));
return;
}
// Add choices to filter dropdown box
foreach (string choice in field.Choices)
{
ListItem filter = new ListItem();
filter.Text = choice;
filter.Selected = true;
listFilter.Items.Add(filter);
}
}
// Show unfiltered ‚mailto‘ link.
btnGenerateLink_Click(null, EventArgs.Empty);
}
}
Nun benötigen wir noch die Implementierung des „btnGenerateLink_Click“ Eventhandlers, welcher den E-Mail Verteiler unter Berücksichtigung des eingestellen Filters erstellt und im HyperLink-Control ausgibt.
protected void btnGenerateLink_Click(object sender, EventArgs e)
{
StringBuilder filterQry = new StringBuilder();
// Gnerate CAML query string from filter listbox
bool bFirst = true;
foreach (ListItem filter in listFilter.Items)
{
if (!filter.Selected) continue;
if (!bFirst) filterQry.Insert(0, „<Or>“);
filterQry.AppendFormat(„<Eq><FieldRef Name='{0}‘ /><Value Type=’Text‘>{1}</Value></Eq>“,
listFilterCol, filter.Text);
if (!bFirst) filterQry.Append(„</Or>“);
bFirst = false;
}
// Empty filter -> show empty, inactive ‚mailto‘ link (but only if
// listFilter.Items.Count > 0 which means that we have a filter field
// configured in the web part)
if (listFilter.Items.Count > 0 && bFirst)
{
linkMailTo.Text = „mailto:“;
linkMailTo.NavigateUrl = String.Empty;
return;
}
// Complete the CAML query string
filterQry.Insert(0, „<Where>“);
filterQry.Append(„</Where>“);
// Setup the CAML query
SPQuery qry = new SPQuery();
qry.Query = filterQry.ToString();
// In the result set we just need the email column
qry.ViewFields = String.Format(„<FieldRef Name='{0}‘ />“, listEmailCol);
// Get SharePoint list and execute the CAML query
SPWeb web = SPContext.Current.Web;
SPList list = web.Lists[listTitle];
SPListItemCollection items = list.GetItems(qry);
// Build ‚mailto‘ link
StringBuilder mailList = new StringBuilder(„mailto:“);
foreach (SPListItem item in items)
{
mailList.AppendFormat(„{0};“, item[0]);
}
if (mailList.Length > 7) mailList.Remove(mailList.Length – 1, 1);
// Show ‚mailto‘ link
linkMailTo.Text = mailList.ToString();
linkMailTo.NavigateUrl = mailList.ToString();
}
Damit ist der Web Part fertig implementiert und kann mit „F5“ gleich mal getestet werden. „F5“ startet die im Projekt Wizard angegebene SharePoint Site und der Web Part wird automatisch in die Web Part Gallary hochgeladen.
Zum Erstellen eines SharePoint Solution Packages für diesen Web Part wählt man im Visual Studio unter dem Build-Menü den Punkt „Package“ aus. Visual Studio erzeugt daraufhin unter dem binRelease-Verzeichnis (bzw. binDebug je nach eingestellter Solution Konfiguration) eine .WSP Datei, welche nun in eine SharePoint Site Collection eingespielt werden kann.
Einspielen der Sandboxed Solution in SharePoint
Zum Einspielen des vorhin erstellten Solution Packages ist in der Top-Level Site der gewünschten SharePoint SiteCollection der Punkt „Site Actions“-„Site Settings“ aufzurufen. Unter den Galleries befindet sich ein Link „Solutions“, über den wir unser Solution Package hochladen können:
Nach Anklicken von „Solutions“ gelangt man zu:
Damit hier der Ribbon mit dem Upload Button sichtbar wird, muss man auf den Reiter „Solutions“ klicken:
Nach Anklicken von „Upload Solution“ erhält man den Upload Dialog:
Nach Betätigen von „OK“ gelangt man zu:
Durch Anklicken von „Activate“ wird das Solution Package zur Solution Gallary hinzugefügt und der Web Part kann nun auf einer beliebigen Web Part Seite in der aktuellen Site Collection hinzugefügt werden.
Hinweis:
Sollte hier der Activate-Button gesperrt sein, so ist in der Share Point Farm das Microsoft SharePoint Foundation Sandboxed Code Service nicht gestartet.
Web Part verwenden
Der in die Site Collection importierte Web Part kann nun auf der gewünschten SharePoint Seite eingefügt werden. Dazu ist unter „Site Actions“ „Edit Page“ auszuwählen und unter dem Reiter „Insert“ der Button „Web Part“ anzuklicken. Unser Web Part ist unter der Kategorie „Custom“ zu finden:
Auf der Seite eingefügt präsentiert sich der Web Part wie folgt:
Über den Punkt „Edit Web Part“ im Web Part Menü lässt sich unser Web Part konfigurieren:
Nach Bestätigen der Konfiguration mit „OK“ erhalten wir beispielsweise:
Nach Anklicken des Mailverteilers öffnet sich automatisch der standardmäßig eingestellte E-Mail Client und fügt im „An:“-Feld den Verteiler ein.
Ist doch cool, oder?