Dem Einen oder Anderen hat Visual Studio wahrscheinlich schon einmal mit dieser leicht dominierenden Bildschirmausgabe überrascht. Wahrscheinlich aber haben es die Meisten noch nie zu Gesicht bekommen, denn wir sind ja keine Copy & Paste Entwickler.
Das ist der besagte Hinweis:
Randbedingungen:
Ich verwende eine virtuelle Maschine(Windows Server 2003) unter Microsoft Virtual Server 2005 R2.
Das Problem tritt gelegentlich auf, wenn innerhalb der Host Maschine etwas kopiert wird und anschließend versucht wird, das soeben kopierte, in Visual Studio, auf der Entwicklungsmaschine, einzufügen.
Lösung:
Wie kann dieses Problem nun gelöst werden? Anfangs dachte ich, der Übeltäter wäre Visual Studio, und beendete einfach den devenv.exe Prozess. Irgendwann irritierte es mich aber, dass sobald diese Meldung auftauchte überhaupt kein Copy & Paste mehr funktionierte. Zu diesem Zeitpunkt fand ich heraus, dass der eigentliche, anfangs nicht verdächtige, Prozess rdpclip.exe der Schuldige war.
Um also in Visual Studio weiter arbeiten zu können, muss einfach der Prozess rdclip.exe beendet werden. Dies kann leicht über den Task Manager vollführt werden.
Falls anschließend wieder Copy & Paste verwendet werden soll, nicht vergessen den RdpClip.exe Prozess wieder zu starten. Gefunden werden kann dieser im Verzeichnis C:\Windows\System32
Wohl jeder Sharepoint Entwickler welcher sich je mit Barrierefreiheit befasst hat, wird schon einmal von dem Alternative Rendering Framework von SPWorks gehört haben. ARF ist ein Open Source Project, welches von Vincent Rothwell entwickelt wurde um Sharepoint etwas barrierefreier zu gestalten. Das Framework beinhaltet mehr als 30 Controls für die Entwicklung barrierefeier Publishing Seiten. Alle Controls erzeugen XML welches mit Hilfe von XSLT letztendlich zu HTML Seiten gerendert werden kann.
Eines dieser Controls, welches aktuell bei uns verwendet wird, ist das ARF Navigations Control. Beim Anlegen einer Überschrift mit Link, kann optional ausgewählt werden, ob die Seite in einem neuen oder in dem aktuellen Fenster geöffnet wird. Dabei ist mir aufgefallen, dass das ARF Menü diese Checkbox schlechthin ignoriert.

Neugierig geworden von der diesjährigen Basta! und Oliver Scheers Vortrag über Silverlight und das .NET RIA Framework, wollte ich das Gehörte heute einmal versuchen in die Praxis umzusetzen.
Das .NET Rich Internet Application (RIA) Framework unterstützt den Entwickler bei der Erstellung n- schichtiger Applikationen. Die .NET RIA Services bilden dabei ein Datenzugriffsmodell welche aus einem Objektmodell (z.B. ADO.NET Entity Framework) einen sogenannten Domain Service zur Verfügung stellen können. Die Hauptzielgruppe dieser Technologie sind .NET Entwickler welche sich vorrangig in Silverlight sowie ASP.NET Anwendungen heimisch fühlen.
Die erste Version der .NET RIA Services kann hier heruntergeladen werden. Es sollte beachtet werden, dass es sich dabei um eine frühe CTP Version handelt.
Nach dem ersten Installationsversuch der .NET RIA Services erhielt ich folgende Fehlermeldung.
The following required components are missing. Microsoft Silverlight 3 Developer Runtime Microsoft Silverlight 3 Beta SDK Microsoft Silverlight 3 Tools.

Da ich die komplette Silverlight 3 Runtime inkl. Silverlight Tools bereits installiert hatte, erschien mir die Fehlermeldung etwas irreführend. Nach kurzer Suche fand ich heraus, dass die .NET RIA Services nicht mit einer deutschen Installation von Visual Studio zusammenarbeiten. Aber wie so oft gibt es auch hier einen nicht dokumentierten Weg um an das Ziel zu kommen
Voraussetzung:
1. Nachdem die .NET RIA Services heruntergeladen wurden in das Downloadverzeichnis wechseln
2. Folgenden Befehl ausführen msiexec /i RiaServices.msi NOCHECK=true
3. Sofern die Installation fehlerfrei abgelaufen ist, folgen nun weitere wichtige Schritte:
4. Nun die Kommandozeile aufrufen und in folgendes Verzeichnis wechseln C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE
5. Von dort aus folgenden Befehl ausführen: devenv /installvstemplates
Sollte die nachstehende Fehlermeldung erscheinen: “Der angeforderte Vorgang erfordert erhöhte Rechte”, muss die Kommandozeile als Administrator ausgeführt werden.
Nach dem Neustart von Visual Studio sollte nun in der Projektvorlagenübersicht .NET RIA Service Class Library

und in dem Dialog Hinzufügen -> Neues Element die Domain Service Class auswählbar sein.

Ein Teil unserer Kernkompetenzen im Umgang mit Sharepoint, ist die Migration von Altsystemen zu Sharepoint. Ein aktuelles Projekt stellte uns vor die Herausforderung, Inhalte, Stylevorgaben und Meta-Daten mittels XML Import aus einem bestehenden Content Management System 1:1 nach SharePoint zu übernehmen. Besonders problematisch war dabei der Fakt, dass sich innerhalb der Daten Parameter für die Businesslogik versteckten. Diese Logik musste in SharePoint zum Teil nachgebaut und beim Import berücksichtigt werden.
Eine Teilaufgabe des Imports bestand in der Übernahme der eigentlichen Inhalte der Seiten. Diese lagen als barrierefreies HTML vor und mussten deshalb original so in die SharePoint Seite importiert werden.
Meine Aufgabe bestand nun darin, den originalen HTML Inhalt der zu migrierenden Seite in eine Sharepoint Seite zu importieren. Möglichst sollten die Optik (Styles, Bilder, etc.) sowie der Inhalt (inkl. Links, Tabellen etc.) unangetastet bleiben.
Sharepoint bietet dem geneigten Entwickler mit seiner API reichlich Werkzeug um diese Aufgabe zu bewältigen. So kann eine Seite ohne Probleme mit folgenden Programmcode angelegt werden:
PublishingWeb currPublishingWeb = PublishingWeb.GetPublishingWeb(webContext);
PublishingPageCollection pages = currPublishingWeb.GetPublishingPages();
PublishingPage currentPage = pages.Add(pageFileName, layout);
Auf diese Weise ist eine Publishing Page schnell erstellt. Soll diese jetzt auch noch mit Inhalt versehen werden, wird das SPField, das für den Inhalt einer PublishingPage zuständig ist, benötigt.
Das SPField für Inhalte ist das PublishingPageContent Field, das über die FieldId Klasse verwendet werden kann.
SPListItem newFileItem = newFile.Item;
newFileItem[FieldId.PublishingPageContent] = htmlContent;
newFileItem.Update();
Bis hier wurde alles ordnungsgemäß von Sharepoint ausgeführt. Die Seite wurde angelegt und der Inhalt wurde auch gesetzt. Beim näheren Betrachten der neu Erstellten Seite wurde ich jedoch misstrauisch:
Durch dieses Verhalten wurden die importierten Seiten “wertlos” für mich. Alle darauf folgenden Versuche den Inhalt in die Seite zu schreiben schlug fehl. Versucht habe ich folgende Wege:
Da ich das Problem gerne ohne “Dirty Hacks” lösen wollte, entschied ich mich eine Supportanfrage bei Microsoft zu stellen. Dazu sei erwähnt, dass die Anfragen über den Microsoft Support sehr schnell und kompetent beantwortet und abgewickelt werden. Ich sollte meine Antwort von Microsoft bekommen; Leider hieß diese “By design” oder kurz auf deutsch: abgewiesen.
Die Begründung: Mirosoft Sharepoint nutzt einen sogenannten XSS (Cross side scripting) Protection Mechanismus. Dieser sollte verhindern das schädlicher Inhalte (Code) in Sharepoint eingepflegt werden kann.
Davon betroffen ist allerdings auch das HTML Texteingabe Control. Beispielsweise würde dieser Programm – Code wie folgt abgeändert:
original: Das ist ein gutes <SCRIPT>void:alert("hello world")</SCRIPT> Script
verfälscht: Das ist ein gutes Script
Auch “<” oder “>” Zeichen würden wie folgt abgeändert: > – <. Ich empfinde dieses Verhalten als vollkommen richtig und auch nachvollziehbar, wenn es dabei bleiben würde. Es stellte sich herraus dass dieser XSS Filter auch für die Kürzung meiner HTML Inhalte zuständig war. Microsoft selbst kann sich nicht erklären warum dieser Filter solch drastische Änderungen am HTML Quellcode vornimmt. Man riet mir von Seiten Microsoft ernsthaft entweder ein 3rd Party AddOn als Ersatz für den RichTextEditor einzusetzen oder aber die Daten nicht innerhalb Sharepoints zu halten, sondern extern. Keiner der beiden angebotetenen Lösungen erschien mir für unser Projekt auch nur ansatzweise logisch beziehungsweise umsetzbar.
Um die Inhalte dennoch wie gefordert 1:1 importieren zu können, musste nun ein Workaround gefunden werden. Dazu bot sich eine Codierung der beim Import beanstandeten HTML-Tags an. Nach der erfolgreichen Integration der Methoden in unseren Import können nun alle Inhalte wie gefordert übernommen werden.
Heute habe ich versucht, über ein Nutzerinterface (GUI) eine Site Collection (Websitesammlung) anzulegen, welche über eine eigene Url erreichbar ist (Host Named Site Collection). Wie erwartet ging dies nicht ohne jegliche Komplikationen über die Bühne.
Um eine Host Named Site Collection anzulegen, stehen dem Entwickler zwei Varianten zur Verfügung. Die erste und von mir bevorzugte ist die programmatische:
Mit der folgenden Methode (z.B. in einer Konsolenanwendung) kann eine Host Named Site Collection angelegt werden:
void createHostNamedSC(string siteUrl,string siteName,string siteDescription)
{
SPWebApplication webApp = SPWebApplication.Lookup(new Uri(SPContext.Current.Web.Url));
SPSiteCollection sites = webApp.Sites;
SPSite Site = null;
Site = sites.Add(siteUrl, siteName, siteDescription, 1033, “STS#0″, “Domain\\Administrator”, “Owner_Display_Name”, “Owner_Email”, “Domain\\Administrator”, “Secondary_Owner_Display_Name”, “Secondary_Owner_Email”, true);
}
Die zweite Variante wird über stsadm realisiert:
Dazu wird in der Console folgender Aufruf gestartet:
stsadm.exe -o createsite
-url http://hnsc.webapplication.com
-ownerlogin Domain\Administrator
-owneremail Administrator@webapplication.com
-hhurl http://www.webapplication.com
Die Webapplication stellt dabei der Eintrag hinter -hhurl (http://www.webapplication.com) dar.
Unter -url wird die gewünschte URL der neuen Site Collection angegeben.
Hat man sich für eine der beiden Methoden entschieden und diese ausgeführt, müssen noch die Hostheader für die Webapplikation angepasst werden. Das Hinzufügen der Hostheader kann einerseits über die Sharepoint Zentral-Administration erfolgen oder aber über den Internet Information Services (IIS) Manager.
Ich habe mich dabei für die Einstellung innerhalb des IIS entschieden.
Dazu öffnet man den IIS Manager und öffnet über das Kontext-Menü die Einstellungen (Properties) der Webapplikation.


Nach diesen Schritten sollte die eben erstelle Site Collection unter ihrer Domain aufrufbar sein.
Nachdem ich diese Schritte alle erfolgreich ausgeführt hatte, versuchte ich mich nun an meiner neuen Host Named Site Collection anzumelden. Obwohl ich augenscheinlich alle Credentials ordnungsgemäß eingegeben hatte, bekam ich folgende Seite zu sehen:
HTTP 401.1 – Nicht autorisiert: Fehler bei der Anmeldung

Nachdem ich schon fast anfangen wollte, mir die Haare auszureißen, fand ich eine Bugbeschreibung von Microsoft unter
Fehler 401.1 beim Aufrufen einer Website
Update:
Spencer Harbar weißt auf seinem Blog, in einen interessanten Artikel, darauf hin, dass dieser Bugfix nicht auf Produktiv – Maschinen eingesetzt werden sollte. Für den externen Zugriff auf die Site Collection tritt dieses Problem in der Regel nicht auf. Deshalb richtet sich dieser Fix nur an Entwickler welche auf der selben Maschine mit mehr als einer Host Named Site Collection arbeiten.
Laut Microsoft tritt dieser Fehler nur auf, wenn die Website integrierte Authentifizierung verwendet und ihr Name der lokalen Loopbackadresse zugeordnet ist. Wenn dann noch Windows Server 2003 mit SP1 installiert ist, schlägt der Fehlerteufel zu. Demnach schlägt die Authentifizierung fehl, wenn der Domänenname oder der benutzerdefinierte Hostheader nicht mit dem lokalen Computernamen übereinstimmen.
Um den Bug zu beheben, müssen folgende Schritte ausgeführt werden.
Nach dem Neustart war ich in der Lage, die Site Collection unter ihrer Domain aufzurufen.
Die letzten Tage habe ich damit verbracht, mich mit den Besonderheiten(oder besser absurden Angewohnheiten) von Sharepoint 2007 zu befassen. Speziell mit dem programmatischen Anlegen von Ordnern und Unterordnern in Sharepoint Dokumenten – Bibliotheken beziehungsweise Listen.
Hier meine gesammelten Erfahrungen über das Anlegen von Ordnern in
Bild- und Dokumentenbibliotheken (Picture- and Documentlibrary)
Angefangen hat das ganze mit dem Versuch, Unterordner in einer Bild- und Dokumentenbibliothek anzulegen. Hier stellte sich Sharepoint gutmütig. Innerhalb dieser Bibliotheken kann über das Menü (Neu /New) ein Ordner angelegt werden, in welchen später auch Inhalte gespeichert werden können.
Soll das Anlegen der Ordner programmatisch (zum Beispiel über ein Feature) erfolgen, kann folgender Programmcode verwendet werden.
String folderList ="Bilder";
SPList spList = webContext.Lists[folderList];
String folderUrl = spList.RootFolder.ServerRelativeUrl.ToString();
SPFolderCollection foldersColl = web.GetFolder(folderUrl).SubFolders;
SPFolder newFolder = folders.Add("Unterordner");
spList.Update();
Bis hierher könnte man meinen, Sharepoint bietet dem Entwickler mit seiner API alle Möglichkeiten, Listen zu modifizieren und so zum Beispiel Ordner anzulegen.
Webseiten Bibliotheken (Pages Library)
Ich wurde jedoch eines Besseren belehrt, als ich versuchte, innerhalb der Webseiten Bibliothek (Pages Library) einen Unterordner anzulegen. Anders als in einer Bildbibliothek bietet hier das Menü nicht die Möglichkeit, einen Ordner hinzuzufügen.

Da das Menü fehlte, dachte ich mir, versuche ich es doch einfach per Programmcode. Hierzu kann der obige Code verwendet werden, indem einfach der String für die Liste auf Pages geändert wird.
String folderList ="Pages";
![]()
Das Ergebnis sieht wie oben angezeigt aus. Der Unterordner erscheint unterhalb der Webseiten Bibiliothek. Eigentlich das gewünschte Ergebnis … aber dieses Ergbnis hat einen Haken. Unterhalb dieses Ordners können keine Pages angelegt werden und der Unterordner hat auch keinen Menüpunkt innerhalb der GUI für das Anlegen einer Page.
Nach intensiver Recherche fand ich einen Knowledge Article von Microsoft zu diesem Thema.
http://support.microsoft.com/kb/948614/en-us
Daraus geht klar hervor, dass dieses Verhalten von Microsoft nicht unterstützt wird. Schade eigentlich.
Wiederverwendbare Inhalte (Reusable Content)
Der letzte Schritt sollte das Anlegen eines Unterordners unterhalb der Wiederverwendbaren Inhalte Bibliothek (Reusable Content) darstellen. Da das Menü die Möglichkeit bietet, bequem einen Unterordner in dieser Liste zu erstellen, dachte ich, der Programmcode von oben sollte sehr gut dafür funktionieren … weit gefehlt. Wieder wurde ich eines Besseren belehrt. Der Code bewirkte in dieser Liste rein gar nix.
Nach einer Phase des Debuggens wurde mir klar, wie Sharepoint hier arbeitet. Anstatt einen SPFolder anzulegen, muss hier ein ein neues SPListItem angelegt werden. Der Trick an der Sache ist, diesem SPListItem den gleichen SPContentType zuzuweisen wie Sharepoint ihn verwendet, um einen Ordner anzulegen.
Wir benötigen den ContentType für Folder. Wird dieser ContentType einen SPListItem zugewiesen, erscheint dieses danach auch in der Wiederverwendbaren Inhalte Liste als Ordner und besitzt alle nötigen Menüpunkte. Der passende SPContentType kann wie folgt ermittelt werden:
SPContentTypeId contentId = new SPContentTypeId("0x0120");
SPContentTypeId listCTID = reuseList.ContentTypes.BestMatch(contentId);
SPContentType cType = reuseList.ContentTypes[listCTID];
List contentTypes = new List();
contentTypes.Add(cType);
Das Ganze habe ich anschließend in eine generische Methode verpackt, welche wie folgt aussieht:

Diese Methode legt nun ein SPListItem an, welches den Content Type Folder besitzt und auch entsprechend in der Liste angezeigt wird. Da der Ordner im Verzeichnisbaum jedoch nicht derselbe ist wie in der Liste angezeigt, muss dieser noch umbenannt werden. Anschließend kann dieser Ordner genauso verwendet werden, als ob er über das grafische Menü angelegt worden wäre. War doch ganz einfach… – oder?
Zum besseren Kopieren hier das Ganze nochmal als Text:
internal static void SubFolder2ReusableList(SPList reuseList, string reusableFolder)
{
reuseList.ContentTypesEnabled = true;
//get the content type for the folder
SPContentTypeId contentId = new SPContentTypeId("0x0120");
SPContentTypeId listCTID = reuseList.ContentTypes.BestMatch(contentId);
SPContentType cType = reuseList.ContentTypes[listCTID];
List<SPContentType> contentTypes = new List<SPContentType>();
contentTypes.Add(cType);
SPListItem newListItem = reuseList.Items.Add();
newListItem[SPBuiltInFieldId.ContentTypeId] = cType.Id;
newListItem[SPBuiltInFieldId.Title] = reusableFolder + "_tmp";
newListItem.Update();
reuseList.Update();
//get the parent folder of the SPListItem which is resident in the left tree
//its not the same folder as listed in die detail list on the right
using (SPWeb webContext = reuseList.ParentWeb)
{
SPFolder reuseFolder = webContext.GetFolder(newListItem.Url);
try
{
//try to rename the folder on the left
reuseFolder.MoveTo(reuseList.RootFolder.ServerRelativeUrl + "/" + reusableFolder);
}
catch (SPException)
{
//if the folder already exist delete it
SPFolder toDeleteFolder = webContext.GetFolder(reuseList.RootFolder.ServerRelativeUrl + "/" + reusableFolder);
toDeleteFolder.Delete();
reuseFolder.MoveTo(reuseList.RootFolder.ServerRelativeUrl + "/" + reusableFolder);
}
//rename the _tmp SPListitem to his final name
newListItem[SPBuiltInFieldId.Title] = reusableFolder;
newListItem.Update();
}
}
Möchte man den ModalPopupExtender aus dem ASP.NET AJAX Control Toolkit verwenden, dann geht das nur mit dem DOCTYPE “XHTML 1.0 Transitional” so richtig reibungslos. Beim CollapsiblePanel gibt es dazu einen Hinweis in der Dokumentation, beim ModalPopup fehlt dieser Hinweis. Das Problem besteht aber auch dort.
Symptome: Das Popup wird nicht korrekt positioniert, zentriert sich nicht und viel zu lange Scrollbalken entstehen.
Gerade wenn man WebParts für SharePoint erstellt, hat man aber nicht immer Einfluss auf den DOCTYPE. Oder wenn man schon Einfluss auf den DOCTYPE hat, kann man ihn nicht immer einfach so ändern, weil dann evtl. andere Komponenten nicht mehr richtig funktionieren oder nicht mehr richtig dargestellt werden.
Der beschriebene Workaround aus der Dokumentation des AJAX Control Toolkit fällt damit als Lösung für uns aus.
Ein anderer Lösungsweg ist, ein Custom Build des ASP.NET AJAX Control Toolkit zu erstellen und darin das “fehlerhafte” Stück JavaScript zu korrigieren.
Dazu besorgt man sich den Quellcode via Codeplex und nimmt die folgenden zwei Modifkationen vor:
switch (Sys.Browser.agent) {
case Sys.Browser.InternetExplorer:
if (document.documentElement && document.documentElement.clientWidth)
clientWidth = document.documentElement.clientWidth;
else if (document.body)
clientWidth = document.body.clientWidth;
//clientWidth = document.documentElement.clientWidth;
if (document.documentElement && document.documentElement.clientHeight)
clientHeight = document.documentElement.clientHeight;
else if (document.body)
clientHeight = document.body.clientHeight;
//clientHeight = document.documentElement.clientHeight;
break;
case Sys.Browser.Safari:
clientWidth = window.innerWidth;
clientHeight = window.innerHeight;
break;
case Sys.Browser.Opera:
clientWidth = Math.min(window.innerWidth, document.body.clientWidth);
clientHeight = Math.min(window.innerHeight, document.body.clientHeight);
break;
default: // Sys.Browser.Firefox, etc.
clientWidth = Math.min(window.innerWidth, document.documentElement.clientWidth);
clientHeight = Math.min(window.innerHeight, document.documentElement.clientHeight);
break;
}
Diese Modifikation bringt dem Toolkit bei, Höhe und Breite ein bisschen besser auszulesen.
Achtung:
Hat man bereits an anderen Stellen im eigenen Code Anpassungen aufgrund dieses Problems vorgenommen, indem man z.B. via CSS oder JavaScript nachträglich die Position eines AutoComplete Feldes korrigiert, so ist dies jetzt möglicherweise nicht mehr notwendig und/oder funktioniert nicht mehr richtig. Hier also nochmal kontrollieren!
this._backgroundElement.style.position = 'fixed';
ersetzen zu
this._backgroundElement.style.position = 'absolute';//'fixed';
Ein paar Zeilen weiter unten:
his._foregroundElement.style.position = 'fixed';
ersetzen zu
this._foregroundElement.style.position = 'absolute';//'fixed';
Diese Modifikation beeinflusst andere Controls nicht, und sorgt nur für die ordentliche Positionierung des Popups.
Außerdem zu beachten:
Wenn man das Control Toolkit mit dem mitgelieferten Schlüssel kompiliert, so wir der selbe PublicKeyToken wie beim Original erzeugt. Daraus entstünde dann möglicherweise folgendes Problem:
Verwenden andere Komponenten auf dem Server auch das AJAX Control Toolkit, so bekommen sie die oben vorgenommenen Änderungen durchgereicht, sofern sie nicht explizit gegen eine bestimmte Version kompiliert wurden.
Man sollte also lieber einen neuen PublicKeyToken erzeugen, um möglichen Kompatibilitätsproblemen im Voraus zu entgehen.
Quelle:
Ramesh Bhaskar – Fixing modalpopupextender position problems
Releaseparty at Atlassian? Confluence 3.2 BETA and 3.1.2 with soms bugfixes were released yesterday. [...]
Tino Schmidt's Vortrag zu Enterprise Mashups auf der webciety, 4.3 Remix the Web http://bit.ly/d26rtA [...]
neuer Blogpost: February Cumulative Update (2010) http://bit.ly/cwxZGE [...]
Webinar am 16.03.: „Communote Enterprise Microblogging - Funktionen und Einsatzbereiche im Unternehmen“ http://bit.ly/96eexF [...]