Webpart Caching

October 10th, 2008 by oliver wirkus

Gerade bei SharePoint-Portalen spielt das Thema "Serverlast" eine nicht unerhebliche Rolle. Als Webpart-Programmierer macht man sich meist um andere Dinge Gedanken, als um das Thema Caching. Hier versucht man eher die Serverlast durch ein durchdachtes Design und intelleigente Programmierung zu verringern. Das Thema "Caching" spielt hier oftmals eine untergeordnete Rolle – zu Unrecht, wie ich finde. Denn auch bei Webparts kann man gut Caching-Mechanismen einsetzen, um die Serverlast zu verringern.

Tobias Zimmergren hat in seinem Blog einen interessanten und lesenswerten Artikel zu diesem Thema ver”ffentlicht.

Add to Technorati Favorites

Benachrichtigungseinstellungen editieren – Tool als Download

September 23rd, 2008 by oliver wirkus

Ein paar Tage ist es nun her seit mich ein Kunde angerufen hat, weil er Probleme mit einigen Benachrichtigungseinstellungen hatte. Was war passiert? Nun, als SharePoint-Neuling hatte er als Administrator ein paar Benachrichtigungen an SharePoint-Listen eingetragen und als zu benachrichtigen Benutzer keine Benutzer, sondern Gruppen aus seinem ActiveDirectory eingetragen. Nach einigen Versuchen hatte er viel zu viele Benachrichtigungen eingetragen und l”ste dadurch eine Flut von eMails aus, sobald Eintr„ge in den Listen ge„ndert wurden. Er rief mich an, weil er wissen wollte, wie er diese Benachrichtigungen wieder l”schen kann.

Ich habe ihm gezeigt, wie er in den Websiteeinstellungen die Benachrichtigungen anzeigen und l”schen kann. Allerding muáte ich ziemlich bald zugeben, dass diese Methode nicht besonders benutzerfreundlich ist. Wie der folgende Screenshot zeigt, werden in dieser Ansicht nur die eingerichteten Benachrichtigungen angezeigt – allerdings ohne weitere Parameter – und so ist es ziemlich mhsam herauszufinden, welche Benachrichtigung beibehalten werden soll und welche aufgrund falscher Parametrierung gel”scht werden soll.

Natrlich konnte ich unserem Kunden weiterhelfen, denn fr solche Problemf„lle hatten wir vor einiger Zeit schon ein kleines Entwicklertool geschrieben. Dieses Tool habe ich etwas berarbeitet und modernisiert und unserem Kunden zur Verfgung gestellt. Es funktioniert ein wenig anders, als die vergleichbare SharePoint-Benachrichtigungsansicht: da Benachrichtigungen zwar nicht physikalisch, aber immerhin logisch mit Listen oder Bibliotheken verbunden sind, haben wir bei diesem Tool die Auswahl von Benachrichtigungen eng mit der Auswahl von Webs und Listen verbunden. Bedeutet: ein Anwender w„hlt in diesem Tool ein Web aus, danach werden ihm alle Listen in diesem Web angezeigt. W„hlt der Benutzer nun noch eine Liste aus, werden ihm alle Benachrichtigungen mit den wichtigsten Parametern angezeigt, die mit der ausgew„hlten Liste logisch verbunden sind.

   

Die wichtigsten Parameter einer Benachrichtigung k”nnen hier ge„ndert werden und es ist auch m”glich, die komplette Benachrichtigung zu l”schen. Mit diesem Tool kann sich ein SharePoint-Administrator sehr schnell einen šberblick ber alle eingerichteten Benachrichtigungen verschaffen. Wer mehr ber die Codierung des Change Type erfahren m”chte, der findet in Harsh's Blog (retrieving user alerts via object model) eine gute Auflistung der einzelnen numerischen Werte.

Dieses Tool stelle ich -wie meine bisherigen Tools auch- fr Interessierte kostenlos zur Verfgung. Gegen eine kleine Registrierung kann sich jeder ein ZIP-Archiv mit alle bisherigen SharePoint-Tools ber diesen Link kostenlos herunterladen. Wie bisher auch erfolgt der Einsatz dieses Tools auf eigenes Risiko.

Informationen ber meine bisherigen SharePoint-Tools finden sich hier und hier.

Add to Technorati Favorites

How to: Fehlende Workflow-Projektvorlagen in VS2008 / Installationsanleitung

September 18th, 2008 by oliver wirkus

Vor Kurzem setzte ich eine virtuelle Umgebung auf, um ein paar Workflows mit Visual Studio 2008 fr SharePoint 2007 zu erstellen. Nach der Installation von Visual Studio 2008 stellte ich mit Verwunderung fest, dass die Projektvorlagen fr die SharePoint-Workflows fehlen. Erwartet h„tte ich die im folgenden Screenshot dargestellten (und in rot markierten) Projektvorlagen:

   

Nach einiger Recherche habe ich dann aber doch noch herausgefunden, welche Optionen man bei der Installation von Visual Studio 2008 ausw„hlen muss, um Projektvorlagen fr SharePoint 2007 Workflows ausw„hlen zu k”nnen. Die ben”tigte Installationsoption zeigt der folgende Screenshot:

   

Etwas verwirrend finde ich die Sache schon, denn in der Beschreibung dieser Option steht eine Menge ber VSTO, aber nichts ber SharePoint und Workflows. Aus diesem Grunde einen kleinen Hinweis an die Visual Studio Product Group bei Microsoft: ein Hinweis auf SharePoint und Workflows in der Beschreibung zu dieser Installationsoption w„re hilfreich und wrde vielen Visual Studio Usern die Auswahl der ben”tigten Installationsoptionen erleichtern.

 

Add to Technorati Favorites

How to: Upload größerer Dateien in eine SharePoint Bibilothek

September 12th, 2008 by oliver wirkus

In unserem Intranet wollten wir die Upload-Gr”áe fr einzelne Dateien bzw. mehrere Dateien erh”hen. In der Zentraladministration gibt es dafr eine Einstellung, die normalerweise auf 50MB steht. Nachdem wir diesen Wert auf 200MB ver„ndert haben, klappt es aber erstaunlicherweise immer noch nicht, eine einzelne Datei in eine SharePoint Dokumentenbibliothek hochzuladen, wenn diese Datei gr”áer als 50MB war.

Nach einigen Recherchen sind wir auf einen KB-Artikel (KB925083) gestossen, der ein „hnliches Problem beschreibt. Aber auch dieser Artikel und die hier beschriebenen L”sungsm”glichkeiten l”sten unser Problem nicht.

Zum Glck gibt es aber noch STSADM – und genau hier wurden wir fndig. Mit folgendem Befehl l„át sich die Dateigr”áe fr Uploads „ndern:

stsadm -o setproperty -propertyname max-file-post-size -propertyvalue 200 -url http://server/  

<server> muss natrlich gegen die tats„chliche URL ausgetauscht werden.

Ich muss zugegben – so langsam werde ich immer mehr zum Fan von STSADM.

 

Add to Technorati Favorites

Neue Versionen der SharePoint-SDKs

September 11th, 2008 by oliver wirkus

Soeben bei Microsoft entdeckt – fr MOSS und WSS gibt es aktualisierte SDKs. Beide liegen nun in der Version 1.4 vor. Wenn ich mir die Auflistung der Neuerungen ansehen, muss ich sagen: der Download lohnt sich. Microsoft hat wieder einiges Neues und Ntzliches fr die SharePoint-Community zusammengestellt.

MOSS SDK Version 1.4

WSS SDK Version 1.4

 

Add to Technorati Favorites

How to: Flash-Animationen in SharePoint anzeigen

September 8th, 2008 by oliver wirkus

Um Flash-Animationen in SharePoint zu verwenden, gibt es unterschiedliche Wege. Der einfachste, aber auch unflexibelste Weg ist, einfach ein Inhaltseditor-WebPart mit ein paar Zeilen HTML-Code zu fllen. Auf diese Weise bekommt man zwar recht schnell eine Flash-Animation auf eine SharePoint-Seite, aber diese Art der L”sung ist mir einfach zu unflexibel. Ich bevorzuge hier eine flexiblere L”sung und setze deswegen ein WebPart ein.

Fr unseren eigenen Internet-Auftritt haben ich ein kleines WebPart entwickelt. Dieses WebPart zieht sich die anzuzeigenen Flash-Animationen aus einer benutzerdefinierten SharePoint-Liste (bzw. aus dem Anhang eines Eintrags) und zeigt diese Animation dann an. Vorteil dieser L”sung: sowohl die SharePoint-Seite, als auch das WebPart mssen nicht ver„ndert werden, wenn ein andere Flash-Animation angezeigt werden soll.

Den Rohbau dieses WebParts m”chte ich hier ver”ffentlichen. Um etwas Rechenleistung einzusparen, habe ich im vorliegenden Fall auf den WMODE-Parameter bzw. die Transparenz-Einstellung verzichtet. Solange man 'nur' eine Flash-Animation auf einer SharePoint-Seite anzeigen m”chte, sind diese Einstellungen nicht notwendig. Die Member-Variablen m_iFlashWidth und m_iFlashHeight geben die Breite und die H”he des Ausgabebereichs an. Die Member-Variable m_strFlashUrl enth„lt die URL der anzuzeigen Flash-Animation. Wer lieber ein Inhaltseditor-WebPart benutzen m”chte, um eine Flash-Animation anzuzeigen, der braucht nur den HTML-Code aus der Render-Methode einzufgen und statt der Member-Variablen feste Werte einzusetzen.

using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;

namespace Technidata.ITS.MOSS.Webparts
{
    public class ITSFlashPlayer : WebPart
    {
        private int m_iFlashWidth = 300;
        private int m_iFlashHeight = 200;
        private string m_strFlashUrl = "";

        public ITSFlashPlayer()
        {
            ExportMode = WebPartExportMode.All;
        }

        protected override void Render(HtmlTextWriter writer)
        {
            StringBuilder strHTML = new StringBuilder();

            strHTML.Append("<OBJECT classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 ");
            strHTML.Append("codebase="
http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" ");
            strHTML.Append(string.Format("Width="{0}" Height="{1}"> ", m_iFlashWidth, m_iFlashHeight));
            strHTML.Append(string.Format("<PARAM NAME="movie" VALUE="{0}"> ", m_strFlashUrl));
            strHTML.Append("<PARAM NAME="quality" VALUE="high"> ");
            strHTML.Append(string.Format("<EMBED src="{0}" quality=high WIDTH="{1}" HEIGHT="{2}" TYPE="application/x-shockwave-flash" PLUGINSPAGE="
http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"></EMBED></OBJECT>", m_strFlashUrl, m_iFlashWidth, m_iFlashHeight));

            writer.Write(strHTML.ToString());
        }
    }
}

Add to Technorati Favorites

Patrick Tisseghem unerwartet verstorben

September 6th, 2008 by oliver wirkus

Vor wenigen Minuten habe ich hier gelesen, dass Patrick Tisseghem am 3. September in Gothenburg (Schweden) offensichtlich an Herzversagen verstorben ist.

Ich hatte die Gelegenheit, Patrick auf den letzten SharePoint Conferences pers”nlich zu treffen und mit ihm zu sprechen. Ich habe Patrick als sehr erfahrenen SharePoint-Architekten kennengelernt, der immer ein offenes Ohr und einen guten Rat fr andere SharePoint-Entwickler oder -Architekten hatte. Die wenn auch kurzen Gespr„che mit ihm waren mir sehr wertvoll und wichtig.

Mit Patrick Tisseghem verliert die weltweite SharePoint-Gemeinde ein wertvolles und aktives Mitglied.

Auch ich m”chte seiner seiner Familie mein tiefempfundenes Beileid aussprechen.

 

Übersicht aller SharePoint-Versionen

August 29th, 2008 by oliver wirkus

Im Blog von Aaron Saikovski habe ich eine interessante Aufstellung ber die aktuellen SharePoint-Versionen gefunden. 

Service Pack/Hotfix Version WSS V3.0 MOSS 2007
Infrastructure Update (KB951695 & KB951297) 12.0.0.6318 12.0.0.6318
Post-SP1 hotfix (KB953137 & KB953138) 12.0.0.6316.500 12.0.0.6316.500
Post-SP1 hotfix (KB952698 & KB952704) 12.0.0.6315 12.0.0.6315
Post-SP1 hotfix (KB948945) 12.0.0.6303 12.0.0.6303
Post-SP1 hotfix (KB941274) 12.0.0.6301 12.0.0.6301
Post-SP1 hotfix (KB941422) 12.0.0.6300 12.0.0.6300
Service Pack 1 12.0.0.6219 12.0.0.6219
Release To Manufacturing (RTM) 12.0.0.4518 12.0.0.4518

 

Hier der Link auf den Artikel im Blog von Aaron Saikovski.

 

Add to Technorati Favorites

How to: Professionelle Datenanzeige mit dem Control SPGridView

August 21st, 2008 by oliver wirkus

Angeregt durch ein WebPart von Ren‚ H‚zser habe ich mir mal das Control SPGridView genauer angesehen. Im Gegensatz zum 'normalen' GridView wird SPGridView von SharePoint selbst verwendet, um z.B. den Inhalt von SharePoint-Listen anzuzeigen. Der groáe Vorteil des SPGridView: dieses Control bietet Untersttzung fr Sortierung, Filterung und Paginierung – und passt sich ohne weitere Programmierung an das Layout von SharePoint an.

Im Internet finden sich einige interessante Artikel darber, wie man eine Datenanzeige mit einem SPGridView realisieren kann. Aber jeder dieser Artikel behandelt leider immer nur einen Teilaspekt – ein umfassendes Beispiel zum Thema SPGridView habe ich nicht gefunden. Aus diesem Grund habe ich selbst das folgende Beispiel geschrieben. Es zeigt beispielhaft die Datenanzeige mit einem SPGridView mit Sortierung, Paginierung und Filterung. Leider zeigt das SPGridView beim Filtern von Spalten kein Filter-Icon an, wie man es von SharePoint-Listen kennt. Hier musste ich selbst ein wenig recherchieren – aber mit Hilfe von Greg Galipeau konnte ich auch dafr eine L”sung finden. Der Trick besteht darin, sich an das Event RowDataBound zu h„ngen, hier die gefilterte Spalte auszulesen und mit diesen Informationen das Filter-Icon selbst in der Kopfzeile des SPGridView in der entsprechenden Spalte anzuzeigen.

Die folgenden beiden Screenshots zeigen das SPGridView in Aktion. Im zweiten Screenshot sieht man, dass das SPGridView auch die Sortier- und Filtericons verwenden und anzeigen kann.

Bevor wir uns jetzt auch noch den Sourcecode dazu ansehen, m”chte ich noch darauf hinweisen, dass der folgende Code ausschlieálich als Beispiel bzw. Anschauungsobjekt gedacht ist. Er ist in der vorliegenden Form nicht dafr geeignet, unver„ndert in eine produktive Umgebung bernommen zu werden.

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

namespace Technidata.ITS.MOSS.Webparts
{
    public class SPGridViewDemo : System.Web.UI.WebControls.WebParts.WebPart
    {
        private SPGridView m_oGridView;
        private ObjectDataSource oDataSource;

        public SPGridViewDemo()
        {
        }

        protected override void CreateChildControls()
        {
            m_oGridView = new SPGridView();

            // Set basic gridview properties
            m_oGridView.ID = "MyGridView";
            m_oGridView.AutoGenerateColumns = false;
            m_oGridView.AlternatingRowStyle.BackColor = System.Drawing.Color.WhiteSmoke;

            // Set properties for sorting
            m_oGridView.AllowSorting = true;

            // Set properties for paging
            m_oGridView.PageSize = 3;
            m_oGridView.AllowPaging = true;
            m_oGridView.PagerStyle.HorizontalAlign = HorizontalAlign.Center;

            // Set properties for filtering
            m_oGridView.AllowFiltering = true;
            m_oGridView.FilterDataFields = "Vorname,Nachname";
            m_oGridView.FilteredDataSourcePropertyName = "FilterExpression";
            m_oGridView.FilteredDataSourcePropertyFormat = "{1} LIKE '{0}'";

            // Set EventHandler for setting the filter icon
            m_oGridView.RowDataBound += new GridViewRowEventHandler(m_oGridView_RowDataBound);
           
            // Set columns of the SPGridView
            CreateGridViewColumns("Vorname");
            CreateGridViewColumns("Nachname");

            // Create the datasource object
            oDataSource = new ObjectDataSource();

            string strTypeName = "Technidata.ITS.MOSS.Webparts.SPGridViewDemo,";
            strTypeName += Assembly.GetExecutingAssembly().FullName;

            oDataSource.TypeName = strTypeName;
            oDataSource.SelectMethod = "FillDataTable";
            oDataSource.ID = "MyDataSource";

            HttpRequest oRequest = HttpContext.Current.Request;
            if ((oRequest.Form["__CALLBACKID"] == null)    ||
                (oRequest.Form["__CALLBACKPARAM"] == null) ||
                (!oRequest.Form["__CALLBACKID"].EndsWith("MyGridView")))
            {
                if (null != ViewState["FilterExpression"])
                {
                    oDataSource.FilterExpression = (string)ViewState"FilterExpression"];
                }
            }

            Controls.Add(oDataSource);

            // Bind SPGridView to datasource object
            m_oGridView.DataSourceID = oDataSource.ID;

            Controls.Add(m_oGridView);

            // IMPORTANT! Call this line after Controls.Add()
            m_oGridView.PagerTemplate = null
        }

        // ——————–

        protected override void OnPreRender(System.EventArgs e)
        {
            ViewState["FilterExpression"] = oDataSource.FilterExpression;
            base.OnPreRender(e);
        }

        // ——————–

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            m_oGridView.DataBind();
            base.Render(writer);
        }

        // ——————–

        void m_oGridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if ((null != sender) && (e.Row.RowType == DataControlRowType.Header))
            {
                string strFilteredColumn = ((SPGridView)sender).FilterFieldName;
                SetGridViewFilterIcon(m_oGridView, strFilteredColumn, e.Row);
            }
        }

        // ——————–

        public void SetGridViewFilterIcon(SPGridView oGridView, string strColumn, GridViewRow oRow)
        {
            if ((false == string.IsNullOrEmpty(strColumn)) && (null != oRow))
            {
                // Show icon on filtered column
                for (int iIndex = 0; iIndex < oGridView.Columns.Count; iIndex++)
                {
                    DataControlField oField = oGridView.Columns[iIndex];

                    if (oField.HeaderText == strColumn)
                    {
                        Image oFilterIcon = new Image();
                        oFilterIcon.ImageUrl = "/_layouts/images/ewr093.gif";
                        oFilterIcon.ImageAlign = ImageAlign.Left;
                        oFilterIcon.Style[System.Web.UI.HtmlTextWriterStyle.MarginTop] = "2px";
                        oFilterIcon.ID = "FilterIcon";

                        Panel oPanel = new Panel();
                        oPanel.Controls.Add(oFilterIcon);

                        oRow.Cells[iIndex].Controls.Add(oPanel);

                        break;
                    }
                }
            }
        }

        // ——————–

        public static DataTable FillDataTable()
        {
            DataTable oDataTable = new DataTable("Bond Actors");
            DataRow row = null;

            // Create the columns
            oDataTable.Columns.Add("Vorname", typeof(string));
            oDataTable.Columns.Add("Nachname", typeof(string));

            // Fill data table
            row = oDataTable.NewRow();
            row["Vorname"] = "Sean";
            row["Nachname"] = "Connery";
            oDataTable.Rows.Add(row);

            row = oDataTable.NewRow();
            row["Vorname"] = "George";
            row["Nachname"] = "Lazenby";
            oDataTable.Rows.Add(row);

            row = oDataTable.NewRow();
            row["Vorname"] = "Roger";
            row["Nachname"] = "Moore";
            oDataTable.Rows.Add(row);

            row = oDataTable.NewRow();
            row["Vorname"] = "Timothy";
            row["Nachname"] = "Dalton";
            oDataTable.Rows.Add(row);

            row = oDataTable.NewRow();
            row["Vorname"] = "Pierce";
            row["Nachname"] = "Brosnan";
            oDataTable.Rows.Add(row);

            row = oDataTable.NewRow();
            row["Vorname"] = "Daniel";
            row["Nachname"] = "Craig";
            oDataTable.Rows.Add(row);

            return oDataTable;
        }

        // ——————–

        private void CreateGridViewColumns(string strColumn)
        {
            BoundField oGridColumn = new BoundField();
            oGridColumn.DataField = strColumn;
            oGridColumn.HeaderText = strColumn;

            // IMPORTANT! This line is needed to display the arrow icons
            oGridColumn.SortExpression = strColumn;
            oGridColumn.Visible = true;

            m_oGridView.Columns.Add(oGridColumn);
        }
    }
}

 

Nachtrag: ich bin noch auf ein kleines Problem gestossen: wenn gleichzeitig die Sortierung und die Filterung aktiviert ist und man dann die Sortierreihenfolge „ndert, funktioniert das Filtern nicht mehr. Aber auch dafr findet sich eine L”sung – in diesem Fall habe ich mir ein paar Zeilen Code bei Bob's SharePoint Bonanza ausgeliehen und gleich in mein obiges Beispiel integriert. Das Prinzip ist: man sichert in den ViewStates den aktuellen Filter und setzt den Filter aus den ViewStates beim Erzeugen bzw. Parametrieren des Objekts wieder.


 

Add to Technorati Favorites

SharePoint-Listen und die Namen der Spalten

August 14th, 2008 by oliver wirkus

SharePoint nutzt u.a. zur Speicherung von Daten Listen und Dokumentbibliotheken. Neben einigen vordefinierten Listen und Bibliotheken kann man auch benutzerdefinierte Listen erstellen und an die eigenen Bedürfnisse anpassen. Bei diesen benutzerdefinierten Listen kann man selbst festlegen, welche Spalten verwendet werden sollen und welchen Datentyp diese Spalten aufnehmen sollen. Und genau bei diesen Spalten bzw. den Namen der Spalten gibt es einiges zu beachten.

Wenn man eine neue Spalte in einer benutzerdefinierten Liste anlegen möchte, wechselt man in die Listen-Einstellungen und klickt dort auf 'Spalte erstellen'. Jetzt gibt man der neuen Spalte einen Namen und wählt einen Datentyp aus einer Liste vordefinierter Datentypen aus. Das sieht dann z.B. so aus, wie in diesem Screenshot dargestellt:

   

Auch wenn man der Spalte nur einen einzigen Spaltennamen zuweisen kann (was auf den ersten Blick auch logisch und völlig selbstverständlich erscheint), existieren neben dem Spaltennamen, den man beim Erstellen einer neuen Spalte vergibt noch zwei weitere Spaltennamen. Diese beiden zusätzlichen Spaltennamen bekommt ein SharePoint-User nur sehr selten zu sehen, ein Programmierer, der ein WebPart, einen Eventhandler, einen Workflow oder einen Timerjob programmiert, sollte aber schon sehr genau wissen, was es mit diesen zusätzlichen Spaltennamen auf sich hat.

Der Spaltenname, der beim Erstellen einer neuen Spalte angegeben wird, wird als Display Name bezeichnet. Wie dieser Name schon vermuten läßt, ist der Display Name der Anzeigename einer Spalte. Dies bedeutet: überall in der Oberfläche wo es um das Anzeigen von Daten und Informationen geht, wird der Display Name (Anzeigename) verwendet.

Beim Erstellen einer neuen Spalte erzeugt SharePoint (oder besser gesagt das unterlagerte Objekt-Modell) zwei weitere Spaltennamen: den Internal Name und den Static Name. Von diesen beiden Spaltennamen bekommt ein SharePoint-User kaum etwas zu sehen und auch ein SharePoint-Administrator oder ein Designer werden diese beiden zusätzlichen Spaltennamen nur selten zu Gesicht bekommen. Dennoch sind beide sehr wichtig und sollten besonders von Entwicklern beachtet werden.

  • der Display-Name wird auch als Anzeigename bezeichnet und wird vom SharePoint-Benutzer beim Anlegen einer Spalte angegeben.
  • der Static-Name wird von SharePoint beim Erzeugen einer neuen Spalte automatisch erzeugt.
  • der Internal-Name wird ebenfalls von SharePoint beim Erzeugen einer neuen Spalte erzeugt.

Jetzt wissen wir, dass es nicht nur einen Spalten-Namen gibt, sondern drei – aber wozu braucht man denn drei Spaltennamen?

In erster Linie sind diese drei Spalten-Namen für Programmierer interessant. Da der Display-Name (also der Anzeigename) nachträglich verändert werden kann, besteht gerade für die Programmierung die Notwendigkeit, nicht-veränderliche Spaltennamen zu haben, um Spalten auch nach der Änderung des Display-Name noch identifizieren zu können. Beim Verändern des Display-Names werden weder Internal-Name noch Static-Name verändert, dennoch ist der Static-Name nicht ganz so unveränderlich, wie der Internal-Name. Im Gegensatz zum Internal-Name kann der Static-Name nachträglich über Aufrufe aus dem SharePoint Objekt-Modell verändert werden. Static-Name und Internal-Name müssen nicht zwingend gleich lauten.

  • der Display-Name ist vom Benutzer direkt über die SharePoint-Oberfläche veränderbar und kann auch nachträglich beliebig oft umbenannt werden.
  • der Static-Name bleibt beim Umbenennen einer Spalte unverändert, ist aber nicht wirklich unveränderbar. Über das Objekt-Modell kann der Static-Name verändert werden.
  • der Internal-Name bleibt ebenfalls beim Umbenennen unverändert und kann auch über Objekt-Modell Aufrufe nicht mehr verändert werden.

Um den Static-Name zu ändern, reichen im Prinzip die folgenden Code-Zeilen: 

SPList oList = …
string strColumnName = …

oList.Fields.GetFieldByInternalName(strColumnName).StaticName = "NeuerName";
oList.Fields.GetFieldByInternalName(strColumnName).Update(true);

Der Internal-Name scheint der wirklich eindeutige und unveränderbare Namen einer Spalte zu sein. Der Static-Name ist für die Programmierung interessant – ein Beispiel dafür ist die Webpart-Programmierung. Bei uns haben wir Richtlinien (oder neu-deutsch: Best Practices) erarbeitet, wie wir welchen Spaltennamen bei der Programmierung einsetzen. Wenn bei einem Webpart über die Webpart-Properties z.B. ein Spaltenname einer SharePoint-Liste angegeben werden soll, verwenden wir dafür grundsätzlich den Display-Name, um dem Designer die Arbeit der WebPart-Parametrierung zu erleichtern. Der Designer kann bei der Parametrierung eines WebParts die gleichen Spaltennamen eingeben, die er auch beim Anlegen der Liste verwendet hat.

Allerdings verwendet dann das eigentliche WebPart natürlich nicht mehr den in die Properties eingegebenen Display-Name, sondern wandelt diesen mit Hilfe der zugehörigen Liste in den Internal-Name. Intern arbeiten unsere WebParts grundsätzlich mit dem Internal-Name. Es hat für uns aber manchmal einen Vorteil, statt des unveränderlichen Internal-Name den nur bedingt unveränderlichen Static-Name zu verwenden. Dieser Vorteil wird deutlich, wenn wir das Thema Mehrsprachigkeit bzw. Variations betrachten. Angenommen wir haben zwei gleiche Listen – eine Liste mit deutschen Anzeigenamen und eine zweite Liste mit englischen Anzeigenamen. Mit beide Listen soll ein selbstprogrammierter Eventhandler verbunden werden (ein Beispiel dazu findet sich hier), der beim Beschreiben einer bestimmten Spalte getriggert werden soll. In diesem Fall würde der Eventhandler mit dem Static-Name der Triggerspalte arbeiten, denn der Display-Name wird sich aufgrund der unterschiedlichen Sprachen unterscheiden. Da der Static-Name zum Glück nicht vollständig unveränderlich ist, kann man -trotz unterschiedlichem Display-Name- den Static-Name nachträglich angleichen. Auf diese Weise kommt man mit einem Eventhandler für zwei sprachlich unterschiedliche Listen aus.

Wie ändert man denn nun den Static-Name einer SharePoint-Spalte, wenn dies nicht über die Oberfläche, sondern nur über das Objekt-Modell geht? Um dies zu zeigen, habe ich ein kleines Tool geschrieben, welches auf unserer Homepage kostenlos zum Download (gegen eine kleine Registrierung) bereitsteht. Dieses Tool erlaubt die Auswahl eines Webs und einer Liste und zeigt die in der Liste vorhandenen Spalten mit ihrem Internal-Name an. Durch Anklicken einer Spalte kann man diese auswählen und dann ggf. Display-Name und Static-Name ändern. Man kann sich so einen schnellen Überblick über alle Spalten einer Liste verschaffen. Bei diesem Tool handelt es sich um ein Entwickler-Tool, welches wir intern bei unseren Entwicklungen nutzen. Für diesen Beitrag habe ich es ein wenig angepasst und aufgeräumt – dennoch bleibt es ein Entwickler-Tool und der Einsatz erfolgt grundsätzlich auf eigenes Risiko!

Bei der Programmierung bzw. bei der Verwendung des SharePoint Objekt-Modells muss man aber sehr aufpassen, welchen Spaltennamen man mit welcher Methode verwenden kann bzw. soll. Leider ist dies im SDK nicht einheitlich geregelt. Es gibt Methoden, bei denen schon aufgrund des Methodennamens klar ist, mit welchem Spaltennamen sie arbeiten: SPFieldCollection.GetFieldByInternalName(name) arbeitet wie der Name bereits andeutet, mit dem Internal-Name einer Spalte, während SPFieldCollection[name] den Display-Name verwendet. Bei SPListItem[name] wird die Sache noch etwas undurchsichtiger: hier sind alle drei Spaltennamen als Parameter erlaubt. Eine erste Übersicht von Methoden und deren Spalten-Parametern findet sich in diesem Blog.

Um zu zeigen, dass es nicht schwierig ist, bei der Programmierung die einzelnen Spaltennamen sauber zu trennen, hier ein kleines Snippet, wie man mit dem Display-Name den zugehörigen Internal-Name ermitteln kann.

private string GetInternalColumnName(SPList oList, string strColumnDisplayName)
{
    string strRetParam = string.Empty;

    try
    {
        strRetParam = oList.Fields.GetField(strColumnDisplayName).InternalName;
    }
    catch
    {
        strRetParam = strColumnDisplayName;
    }

    return (strRetParam);
}
 

Ich hoffe, dass ich mit diesem Beitrag zeigen konnte, wie wichtig es ist, gerade bei der Programmierung darauf zu achten, die unterschiedlichen Spaltennamen-Typen sauber zu trennen und sich vor Beginn der Programmierung zu überlegen, mit welchem Typ von Spaltennamen gearbeitet werden soll. Aus eigener Erfahrung kann ich sagen, dass es sehr aufwändig werden kann, Sourcecode zu debuggen, bei dem dauernd und scheinbar wahllos zwischen allen Spaltennamen-Typen gewechselt wird. Auch hier gilt: ein klar strukturiertes und durchdachtes Design macht das Programmieren und das Debuggen wesentlich einfacher!

Bisher habe ich erstaunlich wenige Blog-Posts zu diesem Thema gefunden – Grund genug für mich, meine eigenen Erfahrungen zu diesem Thema in meinem Blog zusammenzufassen.

Nachtrag: der Link zum kostenlosen Download unserer SharePoint-Tool geht im Text dieses Beitrags etwas unter. Deswegen hier nochmals der Link zu unserer SharePoint-Seite.

 

Add to Technorati Favorites