Wie werden nun diese Sharepoint Listen gezeichnet? Wie könnte nun der neu zu entwickeltende, spektakuläre Cover Flow für Sharepoint aussehen, den man sich gerade noch im Kopf zurecht gerückt hat? Irgendwie muss dieser im Kopf entwickelte Prototyp nun in das Konzept übertragen werden. Spätestens an diesem Punkt steigen die meisten Consultants oder Artgenossen aus. Einige versuchen sich noch hartnäckig mit ihren Copy & Paste Fähigkeiten (Photoshop und Co.) das gewünschte Bild zusammen zu montieren. Aber sind wir doch mal ehrlich: schön ist das nicht.
Wer öfters mal eine Dokumentation oder aber auch ein Fachkonzept schreibt, wird dieses Szenario wahrscheinlich nur zu gut kennen.
Die kleine italienisch/amerikanische Firma Balsamiq Studios hat sich auf die Flagge geschrieben, uns genau in dieser schweren Zeit der “Ideen-Illustration” zu unterstützen. Gegründet und geleitet wird die kleine Firma von Giacomo ‘Peldi’ Guilizzoni, einem Ex – Adobe Software Lead. Mehr über die Gründungsgeschichte von Balsamiq kann in diesem (empfehlenswerten) Blogpost gefunden werden.
Wie sieht so eine “Skizze”, welche mit Balsamiq entworfen werden kann, denn nun aus?
Genau so!
Am 24.02.2010 haben sich die .NET Freaks aus Dresden und Umgebung zur .NET Usergroup bei uns im Hause zusammen gefunden. Diesmal wurde es gruselig. Alexander Groß führte uns durch ein aktuelles Projekt, welches sich rund um die Bestattung und Einäscherung dreht. Die Idee des Vortrages, welcher eigentlich kein Vortrag im engeren Sinne darstellte, war die gemeinsame Betrachtung eines aktuellen Projektes und deren verwendeten Techniken.
Schon nach einigen Minuten kam es zu interessanten Diskussionen.
Alexander zeigte beispielsweiße wie in seinem Projekt Rake verwendet wird um auf einfache Weise Konfigurationen leicht wartbar zu halten. Außerdem wie Rake und MSDeploy zusammen ein super Team darstellen um Anwendungen zu deployen.
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
Jetzt ist schon fast ein halbes Jahr vergangen, als ich mich das letzte Mal mit dem Cross Site Scripting Filter (XSS) von Sharepoint 2007 befasst habe. Dieser stellt einen wesentlichen Bestandteil von Sharepoint dar und bereitete mir damals schon sehr viele Kopfschmerzen. Prinzipiell besteht die Aufgabe des XSS Filters darin, schädlichen Code oder Skripte aus dynamisch generierten HTML Seiten zu entfernen. Dass der Filter manchmal etwas willkürlich arbeitete hatte ich damals in meinen Blogbeitrag bereits gezeigt.
Was bisher geschah: Sharepoint und der eigensinnige XSS – Filter (Bericht)
Grund genug, sich einmal die Unterschiede zwischen Sharepoint 2007 und Sharepoint 2010 anzuschauen.
Um die Unterschiede zu verdeutlichen, habe ich ein HTML Quelldokument, jeweils mit einem Sharepoint 2007 und mit einem Sharepoint 2010 Server programmatisch importiert.
Folgender Programmcode kam dabei zum Einsatz.
class Program
{
static void Main(string[] args)
{
using (SPSite site = new SPSite("http://....."))
{
using (SPWeb web = site.OpenWeb())
{
PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
string pageFileName = "Test";
PageLayout[] pageLayouts = pubWeb.GetAvailablePageLayouts();
PageLayout currPageLayout = pageLayouts[4];
PublishingPageCollection pages = pubWeb.GetPublishingPages();
PublishingPage currentPage = pages.Add(string.Concat(pageFileName,".aspx"),currPageLayout);
string htmlContent = GetFileContent();
currentPage.ListItem[FieldId.PublishingPageContent] = htmlContent;
currentPage.ListItem.Update();
currentPage.Update();
currentPage.CheckIn("Checked in by me");
}
}
}
Die Ergebnisse des Tests zeigt die folgende Tabelle.
Positiv fällt auf, dass Sharepoint 2010 endlich die Anführungszeichen an Attributen unangetastet lässt. Die 2007 er Version löschte derartige Zeichen kompromisslos weg. Kommentare akzeptiert Sharepoint 2010 immer noch nicht als HTML Elemente – sie werden ebenfalls gelöscht. <li> Elemente dürfen keine Bilder als Listen Icons besitzen. Möchte man sein eigenes Icon zu einer Liste hinzufügen sollte auf eine externe CSS Klasse zurück gegriffen werden (Dies ist in jedem Falle zu empfehlen). Die Eigenschaften “inherit” sowie “none” hingegen werden unterstützt.
Script Tags werden völlig korrekt entfernt. Ebenso Iframe Elemente. Diese sind nicht erwünscht.
Weiterhin positiv aufgefallen ist, dass Elemente des Typs <input/> endlich korrekt geschlossen werden. Das Attribut “Name” wird leider gelöscht. Warum kann ich mir nicht erklären, es scheint aber so, als würden alle Attribute mit der Bezeichnung “name” gelöscht.
Als letzte Besonderheit fällt auf, dass Sharepoint nun konsequent alle absoluten Urls in relative überführt. In Sharepoint 2007 blieben absolute Urls unangetastet. Relative Urls, welche keinen Bezug zu dem aktuellen Sharepoint Server besitzen, wie etwa <a href=”../../beispiel.htm”>, werden weiterhin gelöscht.
Fazit: Es scheint als hätte sich das Sharepoint Entwicklungsteam einige Gedanken über XHTML & Co gemacht. So fallen die geschlossen Tags sowie die Anführungszeichen positiv auf. Einige Baustellen bleiben weiterhin offen.
Im vorangegangenen Blogbeitrag über das Client object model, habe ich beschrieben wie mittels Context.Executequery() eine synchrone Anfrage an den Sharepoint Server abgesetzt werden kann. In diesem Eintrag werde ich das Gegenstück Context.ExecuteQueryAsync() etwas näher beleuchten. Es ist etwas verwirrend, dass Microsoft hier zwei Methoden anbietet, um Anfragen an Sharepoint zu senden. Als ich erstmalig die Methode ExecuteQuery() aufgerufen habe, erhielt ich eine Exception, welche mir mitteilte, dass ich diese Methode nicht in einem UI Thread aufrufen darf.
InvalidOperationException. The method or property that is called may block the UI thread and it is not allowed.
Aus diesem Grund, muss bei Verwendung der Methode ExecuteQuery(), in einem UI Prozess, ein Thread gewählt werden, welcher das UI nicht beeinträchtigt.
ThreadPool.QueueUserWorkItem(new WaitCallback(LoadSharepointContext));
Nach einer kurzen Suche bin ich auf die Erklärung der MSDN gestoßen.
The Silverlight client object model provides both an ExecuteQuery() method, which can be called synchronously from threads that do not modify the user interface (UI), and an asynchronous ExecuteQueryAsync(ClientRequestSucceededEventHandler, ClientRequestFailedEventHandler) method for cases where threads do modify the UI
Soll das Laden der Sharepoint Daten in einem User Interface Thread erfolgen, muss also zwingend die Asynchrone Methode verwendet werden. Falls der Programmcode keine Änderung an der UI vornimmt, kann weiterhin die synchrone Methode verwendet werden. Wie die asynchrone Query zu verwenden ist, zeige ich im nachfolgendem Beispiel.
Voraussetzungen für dieses Beispiel:
Die Voraussetzungen für dieses Beispiel sind analog der, des ersten Blogeintrages:
Los geht’s:
1. Es sind die Schritte 1. – 6. des Blogeintrages “Sharepoint 2010: Client object model & Silverlight – synchroner Ansatz” auszuführen.
2. Die Abarbeitung der Query varriert jedoch zu dem synchronen Ansatz.
ClientContext clientCxt = new ClientContext("http://siteCollectionAdresse");
List shoppingList = clientCxt.Web.Lists.GetByTitle("Einkauf");
CamlQuery query = CamlQuery.CreateAllItemsQuery();
ListItemCollection listItems = shoppingList.GetItems(query);
clientCxt.Load(listItems);
clientCxt.ExecuteQueryAsync(new ClientRequestSucceededEventHandler(OnSuccess), new ClientRequestFailedEventHandler(OnFailed));
Wie zu erkennen, wird diesmal die Methode “ExecuteQueryAsync” aufgerufen. Diese benötigt als Paramater einen ClientRequestSucceededEventHandler sowie einen ClientRequestFailedEventHandler. Beide werden wie folgt erzeugt:
private void OnSuccess(Object sender, ClientRequestSucceededEventArgs args)
{
}
private void OnFailed(Object sender, ClientRequestFailedEventArgs args)
{
}
3. Bei erfolgreicher Abarbeitung der Anfrage, sollte diese im Successhandler landen, wo die weitere Verarbeitung der Daten stattfinden kann.
private void OnSuccess(Object sender, ClientRequestSucceededEventArgs args)
{
foreach (ListItem item in listItems)
{
einkaufList.Add(new EinkaufData
{
Title = item["Title"].ToString(),
Details = item["Details"].ToString(),
Preis = item["Preis"].ToString()
});
}
}
4. Achtung: Die Verarbeitung in OnSuccess findet in einem separaten Thread statt (nicht UI Thread). Nimmt man Änderungen an dem User Interface vor, muss der Dispatcher verwendet werden.
disp.BeginInvoke(() =>
{
dataGrid.ItemsSource = einkaufList;
});
5. Ist alles erfolgreich geladen, sollte das Datagrid wie folgt aussehen.
Eines, der für mich meist erwarteten Features von Sharepoint 2010, ist das neue Client object model. Gerade hinsichtlich der Entwicklung von Silverlight Web Applikationen in Verbindung mit Sharepoint, erleichtert es uns deutlich die Arbeit. Bisher mussten umständlich Serveranwendungen geschrieben werden um dann per Sharepoint Webservices auf die API zurück zu greifen. Das Client object model zieht nun eine neue Abstraktionsschicht ein, um diese Zugriffe zu erleichtern. Mit Hilfe des Client object models stehen fast alle Eigenschaften und Daten einer Site Collection zur Verfügung, so zum Beispiel der Zugriff auf Listen.
Das Client object model steht für nahezu alle Technologien zur Verfügung. Ob WPF, Forms Anwendungen, Silverlight oder Javascript.
In diesem ersten Überblick zeige ich wie das Client object model verwendet werden kann, um Daten aus einer Sharepoint 2010 Liste auszulesen. Das Auslesen der Daten soll in einer Silverlight Web Applikation stattfinden. Diese soll nicht, wie in den meisten Beiträgen zum Client object model, in Form eines Sharepoint Webparts erstellt werden, sondern außerhalb von Sharepoint laufen.
Voraussetzungen für dieses Beispiel:
Los geht’s:
1. Im ersten Schritt muss ein neues Silverlight 3 Projekt innerhalb von Visual Studio angelegt werden. Zum Beispiel Silverlight 3 Navigation Application.
2. Die folgenden beiden DLLs werden als Referenz in dem Silverlight Projekt benötigt.
Wenn Visual Studio 2010(Beta 2) verwendet wird und nach dem Hinzufügen der beiden DLLs ein kleines rotes Ausrufezeichen an der Referenz kleben sollte, habt ihr nichts falsch gemacht. Dabei handelt es sich um einen Bug von Visual Studio 2010. Der Fehler ist in der Pfadtiefe des Projektes und der Silverlight DLLs begründet. Um den Fehler zu beheben habe ich das Projekt einfach unter C:\Projects gelegt.
3. Da sich Sharepoint 2010 und das Silverlight Projekt in einer unterschiedlichen Domain befinden, wird der Zugriff auf den Client Context verweigert. Silverlight benötigt eine Clientaccesspolicy.xml Datei welche bestimmt, ob der Zugriff autorisiert ist. Diese Datei muss sich im Rootverzeichnis des Webservers befinden. Hier kommen die domain policy helper von Tim Heuer ins Spiel. Innerhalb des Webprojektes der Silverlightanwendung wird eine XML Datei mit den Namen Clientaccesspolicy.xml erstellt.
In dieser Datei wird das Snippet Menü via STRG+K+X aufgerufen und das Silverlight Clientaccesspolicy.xml Snippet ausgewählt. Der folgende Inhalt sollte erscheinen.
Wichtig: Vor Verwendung der Datei muss ein IIS Reset erfolgen.
4. Auf der darstellenden Seite benötigen wir ein Anzeigeelement für die Listen Daten. Dazu empfiehlt sich ein Datagrid. Dieses kann, basierend auf einem Datenobjekt, seine Spalten dynamisch generieren.
<data:DataGrid AutoGenerateColumns="True" Height="200" Name="einkauf" Width="311" HorizontalAlignment="Left" />
Mit diesem XAML Code wird ein Datagrid mit dem Namen “einkauf” erstellt, welches automatisch seine Spalten generiert.
5. Auf Basis der Sharepoint Liste wird ein Datenobjekt erstellt.
public class EinkaufData
{
public string Title {get;set;}
public string Preis { get; set; }
public string Details { get; set; }
}
Dieses wird benötigt um das “einkauf” Datagrid zu befüllen.
6. Basierend auf dem Datenobjekt wird eine Liste erstellt.
private List einkaufList = new List();
7. Wie im Titel erwähnt, nutze ich in diesem Beispiel die synchrone Datenübertragung. Für synchrone Anfragen wird die Methode ExecuteQuery() genutzt, für asynchrone ExecuteQueryAsync . ExecuteQuery darf nicht eingesetzt werden, falls damit das Laden des User Interfaces beeinträchtigt wird. Falls die Methode trotzdem verwendet wird, tritt folgende Exception auf.
InvalidOperationException. The method or property that is called may block the UI thread and it is not allowed.
Um dieser Exception aus dem Weg zu gehen, wird die Methode LoadSharepointContext in einem Hintergrundprozess ausgeführt.
ThreadPool.QueueUserWorkItem(new WaitCallback(LoadSharepointContext));
private void LoadSharepointContext(Object stateInfo)
{
ClientContext clientCxt = new ClientContext("http://siteCollectionAdresse");
List shoppingList = clientCxt.Web.Lists.GetByTitle("Einkauf");
CamlQuery query = CamlQuery.CreateAllItemsQuery();
ListItemCollection listItems = shoppingList.GetItems(query);
clientCxt.Load(listItems);
clientCxt.ExecuteQuery();
foreach (ListItem item in listItems)
{
einkaufList.Add(new EinkaufData
{
Title = item["Title"].ToString(),
Details = item["Details"].ToString(),
Preis = item["Preis"].ToString()
});
}
}
8. War das Laden des Sharepoint Kontextes erfolgreich, sollte die einkaufList nun mit den Daten der Sharepoint Liste gefüllt sein.
Als letzter Schritt muss nun die Liste dem Datagrid als Quelle zur Verfügung gestellt werden. Dabei muss beachtet werden, dass die Liste nicht im User Interface Thread befüllt wurde. Hier kommt der Dispatcher zum Zug.
Dispatcher.BeginInvoke(() =>
{
einkauf.ItemsSource = einkaufList;
});
9. War alles erfolgreich sollte das Datagrid wie folgt aussehen.
Tipp: Sollte ein Zugriff auf eine Eigenschaft eines SP Objektes erfolgen, ohne die Query vorher abgesetzt zu haben, erhält man die folgende Exception :
PropertyOrFieldNotInitializedException. Diese Exception tritt solange auf, bis eine Eigenschaft geladen und die Query mittels ExecuteQuery abgesetzt wurden ist.
Wie die asynchronen Anfragen an Sharepoint mit dem Client object model realisiert werden, zeige ich im nächsten Blogeintrag.
Für alle, die sich mit dem neuen Visual Studio und dem .NET Framework 4.0 vertraut machen wollen oder mehr erfahren möchten, hat Microsoft das neu aktualisierte Visual Studio 2010 and .NET Framework 4 Training Kit veröffentlicht. Das am 11.01.2010 veröffentlichte 151 MB große Paket enthält eine Vielzahl von Präsentationen, Demos und Tutorials. Genau genommen 17 Präsentationen, 21 Demos und 26 Tutorials sowie 10 Videos. In dieser Version des Kits wird auch auf die Themen Office, SharePoint und Application Lifecycle Management eingegangen. Der Download lohnt sich auf alle Fälle.
Am Mittwoch dem 15.12.2009 wurde das Cumulative Update Dezember 09 für Windows SharePoint Services 3.0 und Microsoft Office SharePoint Server 2007 veröffentlicht. Über die folgenden Links können sowohl das WSS 3.0 als auch das MOSS 2007 Full server package heruntergeladen werden.
WSS 3.0
Das Paket beinhaltet die folgenden Hotfixes:
MOSS 2007
Das Paket beinhaltet die folgenden Hotfixes:
Installation:
Nach erfolgter Installation des Service Pack 2 für MOSS und WSS können die Server packages 977026 & 977027 installiert werden.
Im Anschluss muss der Sharepoint Configuration Wizard ausgeführt werden.
Am 2. Dezember 2009 fand in Düsseldorf der 2. iX Day rund um SharePoint statt. Nach dem Erfolg des ersten iX Tages im Juli sollte sich diesmal alles rund um Sharepoint, speziell Sharepoint 2010 drehen. In über 25 Sessions kam der ambitionierte Sharepointer voll auf seine Kosten. Das Themengebiet erstreckte sich von entwicklerlastigen Vorträgen, welche sich mit der API Unterstützten Programmierung von Sharepoint befassten über Vorträge der administrativen Art bis hin zur neuen Sharepoint Pie.
Durch die Integration von PowerShell in SharePoint 2010 geht Microsoft endlich einen Weg in die richtige Richtung. Schon im Beta Status sind sehr viele STSADM Befehle entfernt und nur sehr wenige hinzugefügt wurden. Ungefähr 20 Befehle wurden entfernt und nur 6 hinzugefügt. Dies ist einfach nachzuvollziehen in dem
stsadm -help
jeweils auf einem Sharepoint 2007 System und auf einem Sharepoint 2010 System ausgeführt und anschließend die Ausgabe verglichen wird. Ich finde diesen Weg richtig cool. Wahrscheinlich weil ich mich mit STSADM nie so richtig anfreunden konnte.
PowerShell eröffnet dem geneigten Administrator oder Entwickler jetzt vollkommen neue Ansätze Sharepoint zu administrieren.
Jeder Entwickler , welcher mit dem Sharepoint Objekt Modell schon etwas vertraut ist, wird vermutlich wissen, dass Instanzen von SPSite, SPWeb oder im allgemeinen alle Klassen welche IDisposable implemtieren, sehr viele Ressourcen verbrauchen können. Gleich zum Start hat das Sharepoint Team nun zwei CMDLETS entwickelt welche den Umgang mit Disposable Objekten vereinfachen sollen und uns das Leben erleichtern.
Start-SPAssigment
Stop-SPAssigment
Es gibt drei Levels des Assignments.
No Assignment
Diesen Weg sollte jeder kennen. Es wird ein SPWeb Objekt erstellt, welches verarbeitet aber nicht mehr disposed wird.
$web = Get-SPWeb "http://localhost" $web.Title = "Hallo SharePoint Usergroup" $web.Update()
Simple Assignment
Beim “simple assignment” werden alle Objekte dem “global assignment store” zugewiesen. Der Aufruf erfolgt per
Start-SPAssignment -Global
Das “Disposen” aller Objekte erfolgt beim Aufruf von
Stop-SPAssignment
Start-SPAssignment -Global $web = Get-SPWeb "http://localhost" $web.Title = "Hallo SharePoint Usergroup" $web.Update() Stop-SPAssignment -Global
Advanced Assignment
Beim “advanced assignment” werden alle Objekte einem “named store” zugewießen. Das “Disposen” erfolgt durch den Aufruf von Stop-SPAssignment -Bezeichner
$gc = Start-SPAssignment $site = $gc | Get-SPSite "http://localhost" $site.Allwebs $gc | Stop-SPAssignment
Zu beachten wäre noch dass beim Schließen der PowerShell alle Objekte “disposed” werden.
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 [...]
jetzt online! vortrag @jeos zu communote - enterprise #microblogging (ab min. 6:30) http://bit.ly/bONP34 #webciety #cebit [...]