Startseite > Techblog > Artikel mit dem Tag: workaround
thu

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:

Here you can see the error message thrown by visual studio

RDClip

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

Kommentar Feed Trackback URL
thu

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.

Properties

Artikel vollständig lesen »

Kommentar Feed Trackback URL
thu

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.

incompatible versions

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:

  • installiertes Visual Studio 2008 SP1
  • Silverlight 3 SDK
  • Silverlight 3 Tools für Visual Studio

1. Nachdem die .NET RIA Services heruntergeladen wurden in das Downloadverzeichnis wechseln
2. Folgenden Befehl ausführen msiexec /i RiaServices.msi NOCHECK=true

  • Dieser Befehl bewirkt, dass der Windows Installer aufgerufen wird, ohne jegliche Prüfung durchzuführen

3. Sofern die Installation fehlerfrei abgelaufen ist, folgen nun weitere wichtige Schritte:

  • Wechsel in das Verzeichnis C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight\1033
    Darin befinden sich die zwei Zip Dateien BusinessApplication.zip und RIAServicesLibrary.zip.
    Diese beiden Dateien müssen nun in das deutsche Verzeichnis kopiert werden, zum Beispiel für eine deutsche Installation
    C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight\1031
    Durch diese Aktion kann nun innerhalb des Neu->Projekt Dialoges das RIA Template gewählt werden
  • Um die Funktionen rund um die Domain Service Class und Authentifizierung nutzen zu können, müssen nun noch die Element Vorlagen kopiert werden. Dazu  in den folgenden Ordner wechseln C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\1033 und folgende Dateien in das deutsche Verzeichnis kopieren C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\1031
    - AuthenticationDomainService.zip
    - BusinessLogic.zip
    - SearchSitemap.zip
    - AdoNetDataService_DomainServiceCSharpWap.zip

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

  • Visual Studio installiert nun alle neu gefundenen Templates für Projekte und Elemente

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

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

ria2

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.

incompatible versions

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:

  • installiertes Visual Studio 2008 SP1
  • Silverlight 3 SDK
  • Silverlight 3 Tools für Visual Studio

1. Nachdem die .NET RIA Services heruntergeladen wurden in das Downloadverzeichnis wechseln
2. Folgenden Befehl ausführen msiexec /i RiaServices.msi NOCHECK=true

  • Dieser Befehl bewirkt, dass der Windows Installer aufgerufen wird, ohne jegliche Prüfung durchzuführen

3. Sofern die Installation fehlerfrei abgelaufen ist, folgen nun weitere wichtige Schritte:

  • Wechsel in das Verzeichnis C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight\1033
    Darin befinden sich die zwei Zip Dateien BusinessApplication.zip und RIAServicesLibrary.zip.
    Diese beiden Dateien müssen nun in das deutsche Verzeichnis kopiert werden, zum Beispiel für eine deutsche Installation
    C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight\1031
    Durch diese Aktion kann nun innerhalb des Neu->Projekt Dialoges das RIA Template gewählt werden
  • Um die Funktionen rund um die Domain Service Class und Authentifizierung nutzen zu können, müssen nun noch die Element Vorlagen kopiert werden. Dazu  in den folgenden Ordner wechseln C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\1033 und folgende Dateien in das deutsche Verzeichnis kopieren C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\1031
    - AuthenticationDomainService.zip
    - BusinessLogic.zip
    - SearchSitemap.zip
    - AdoNetDataService_DomainServiceCSharpWap.zip

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

  • Visual Studio installiert nun alle neu gefundenen Templates für Projekte und Elemente

Sollte die nachstehende Fehlermeldung erscheinen: “Der angeforderte Vorgang erfordert erhöhte Rechte”, muss die Kommandozeile als Administrator ausgeführt werden.

Kommentar Feed Trackback URL
thu

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:

  • Aus einfachen Links wie zum Beispiel <a href=”../../beispiel.htm”>Beispiel</a> wurde <a>Beispiel</a>.
  • Kommentare wie <!– comment –> wurden einfach gelöscht
  • Auch Attributen wie beispielsweise Ids oder Klassen(class)  in Divs wurden gelöscht
  • Anführungszeichen wurden entfernt – <div style=”test”/> wird zu <div style=test/>

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:

  1. Den Inhalt zu encodieren und anschließend wieder zu dekodieren. Prinzipiell hätte diese Variante funktioniert, jedoch hätte ich die Render Methoden des Sharepoint RichtTextEditors überschreiben müssen. Das hätte wiederum den Nachteil das die Editor Funktion nicht mehr ordnungsgemäß arbeitet. Der ausschlagegebende Faktor diese Variante nicht zu verwenden war jedoch die fehlende Möglichkeit der Indexierung des Inhaltes, da bei dieser Variante der Inhalt in Base 64 – codierter Form in der Sharepoint Datenbank gespeichert worden wäre und so durch die Suche nicht mehr indexiert werden kann.
  2. In einem zweiten Versuch, lud ich mir den Stream der neu angelegten Seite (auf File – Ebene) und ersetzte den von Sharepoint beschädigten HTML Inhalt durch den originalen. Leider wurde dieser Inhalt beim Speichern der Datei erneut beschädigt.
  3. Einen dritten Versuch ersparte ich mir, da dieser die Modifizierung der Sharepoint Datenbank vorgesehen hätte. Ich glaube der Erfolg hätte sich auch in Grenzen gehalten?!

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: &gt – &lt. 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.

Lösung:

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.

Kommentar Feed Trackback URL
thu

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.

iis1

iis2

  • Anschließend wählt man Advanced
  • Menüpunkt Add wählen
  • Als letzter Schritt muss der Port und die Domain noch eingetragen werden
  • Alles bestätigen und einen IIS Reset durchführen (ggf. host Datei Domain eintragen)

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

iiserror

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.

  • Registry Editor öffnen mit “regedit”
  • Schlüssel HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa suchen
  • auf LSA mit rechter Maustaste drücken ->Neu->DWORD
  • Name DisableLoopbackCheck vergeben und Wert 1 eintragen
  • Computer neu starten

Nach dem Neustart war ich in der Lage, die Site Collection unter ihrer Domain aufzurufen.

Kommentar Feed Trackback URL
thu

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)
  • Webseiten Bibliotheken (Pages Library)
  • Wiederverwendbare Inhalte (Reusable Content)

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.

Pagesfolder

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";

Pagestest

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:

CodeSnippet
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();
 }
 }

Kommentar Feed Trackback URL
che

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:

  • AjaxControlToolkit\Common\Common.js 
    • Darin sucht man nach “getClientBounds” und ersetzt das in der Funktion enthaltene SWITCH Statement durch folgendes:
              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!

  • AjaxControlToolkit\ModalPopupExtender\ModalPopupBehavior.js 
    • Dort in der “initialize” Funktion folgende Ersetzungen vornehmen: 
      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 BhaskarFixing modalpopupextender position problems

Kommentar Feed Trackback URL

Tag Cloud

Unsere Themen

Kommentare

  • SharePoint_Team: Rückblick zum Treffen der .NET Usergroup Dresden am 24.02.2010: im #Communardo #Techblog...
  • TorstenHu: Rückblick zum Treffen der .NET Usergroup Dresden am 24.02.2010: im #Communardo #Techblog...
  • SharePoint_Team: Neuer Blogpost zur #BastaCon im #Communardo #TechBlog: http://tinyurl.com/yjqyqpb This comment was...
  • SharePoint_Team: Nur noch etwa 1 Stunde, dann beginnt die .NET Usergroup… http://bit.ly/dxDoKg This comment was...
  • SharePoint_Team: RT @TorstenHu: ViS is waiting for an operation oder Warum Copy & Paste schlecht ist: #Communardo...

Twitter