Allgemein
Knowledge Base
- Neue Struktur (In Arbeit)
- Computertechnisches
Community
Privat
Um einigermaßen schmerzfrei Web Parts entwickeln zu können sollte die erstellte dll im GAC (Global Assembly Cache) des Webservers residieren. Dann gilt sie als sicher und man hat alle Möglichkeiten die das .NET Framework bietet. Ansonsten kann man keine Dateien schreiben, keinen HTTP-Request absetzen etc. Der Nachteil ist aber, daß man nach jeder Änderung einen iisreset
machen muß, damit der Webserver die neue dll benutzt - sofern sich die Versionsnummer der Assembly nicht ändert (siehe unten).
Das Web-Part muß "strongly named" sein wenn seine Assembly im GAC liegt, sonst verweigert der Sharepoint mit einer Sicherheitsmeldung die Ausführung. Dafür muß Web-Part-Assembly mit einem Schlüssel verknüpft werden. Der Schlüssel ist wiederum mit der Versionsnummer verknüpft, d.h. eine andere Versionsnummer hat einen anderen öffentlichen Schlüssel. Deshalb sollte zur Einfachheit während der Entwicklung die Versionsnummer festgenagelt werden, und sich nicht mit jedem Build ändern. Die Versionsnummer befindet sich in der AssemblyInfo.cs
, wenn sie * enthält wird sie bei jedem Build hochgezählt - wir setzen sie fest: [assembly: AssemblyVersion("1.0.0.0")]
Um ein Webpart 'strongly named' und damit vertrauenswürdig zu machen sind folgende Schritte notwendig:
Es ist eine Datei mit einem Schlüsselpaar nötig. Dazu existiert ein Kommandozeilen-tool im Visual Studio .NET Installations-Verzeichnis
(\Programme\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin\
).
Eine Schlüsseldatei wird erstellt mit: sn.exe -k c:\keypair.snk
Man erstellt sich besten einmalig ein Keyfile und verwendet es für alle Projekte.
In der AssemblyInfo.cs
muß das keypair.snk
-File referenziert werden:
[assembly: AssemblyKeyFile("c:\\keypair.snk")]
bzw. wenn es im Quellcode-Verzeichnis des Webpart-Projektes liegt:
[assembly: AssemblyKeyFile("..\\..\\keypair.snk")]
Das Keyfile darf nicht auf den Ziel-Server deployt werden. Erstens wird es nicht benötigt, zweites ist es eine Sicherheitslücke, denn der Angreifer erhält damit den privaten Schlüssel.
sn -T <assemblyname.dll>
C:\windows\assembly
) reinziehen, Public Key wird dann im Dateifenster ersichtlich.
<Assembly>Assemblyname ohne .dll, Version=<Versionsnummer>,
Culture=neutral, PublicKeyToken=<Public Key Token (mit sn ermittelt)></Assembly>
<Assembly>Elsni.Webparts.tollesWebpart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=27828b94c818161e</Assembly>
Manifest.xml
wie folgt eintragen:<SafeControl Assembly="Elsni.Webparts.tollesWebpart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=27828b94c818161e"
Namespace="Elsni.Webparts" TypeName="*" Safe="True" />
.dwp
-files sollten bereits vom Build-Typ "Inhalt" sein, nachträglich erstellte .dwp
-files sind per default nicht eingebunden. (In den Eigenschaften des dwp-files die Buildaktion auf 'Inhalt' setzen).
C:\Programme\Gemeinsame Dateien\Microsoft Shared\web server extensions\60\BIN\stsadm.exe -force -o addwppack -globalinstall -filename <''CAB-FILE''>
iisreset
(Die Zeilen sind sehr lang und aus anzeigetechnischen Gründen umgebrochen)
Das finale Deployen zum Kunden ist glücklicherweise relativ einfach aus der Entwicklungsumgebung heraus:
<SafeControls>
Sektion des Manifest.xml
files muß den gleichen Eintrag enthalten, wie die gleichnamige Sektion der web.config
- Wichtig ist hier natürlich wieder mal der Public Key.
<DwpFiles>
Sektion muss alle zu deployenden Web-Parts in der Form <DwpFile FileName="SiteMap.dwp"/>
enthalten
dwp
-Files muss die Build-Property auf "Inhalt" gesetzt werden, sonst werden sie nicht mit in die CAB-Datei gepackt.
Die fertige CAB-Datei kann dann einfach mit stsadm
in den Kundenserver eingebunden werden, die Sicherheitsmechanismen werden automatisch konfiguriert. Voraussetzung ist, daß der ausführende User dbo-Rechte auf der config-Datenbank das SQL-Servers hat.
stsadm
tritt der Fehler System.Exception oder Object Reference not set to instance of an object auf:Manifest.xml
und assemblyinfo.cs
durchsehen. Es könnte ein vereinsamtes Gänsefüßchen (Anführungsstrich, Tüttel, Hochkomma etc.) und damit eine nicht abgeschlossene Zeihenkette dafür verantwortlich sein. Es kann sich auch um einen anderen Schreibfehler in einer der Konfigurationsdateien handeln. Kandidaten dafür sind auch die dwp
Files, im <Assembly>
Tag z.b. dürfen keine Fehler sein!
stsadm
tritt der Fehler "Die Webpartpaket-datei kann in der Konfigurationsdatenbank nicht gefunden werden" aufstsadm
tritt der Fehler "Ungültige Daten auf Stammebene. Zeile 1, Position 1."(o.ä.) auf.dwp
oder Manifest.xml
) validiert nicht. Müllzeichen?
Manifest.xml
eingetragen
bin
-Verzeichis des des Webservers, also standardmäßig in C:\inetpub\wwwroot\bin
installiert, es sei denn man installiert mit der option -globalinstall
dann liegt die dll im Global Assembly Cache (GAC), also in C:\windows\assembly
. Im letzteren Fall muß die Assembly signiert sein.
C:\inetpub\wwwroot\wpcatalog
C:\inetpub\wwwroot\wpresources
[Browsable(true), | Property erscheint in der Property-Liste |
Category("Miscellaneous"), | Unter welcher Kategorie erscheint die Property |
DefaultValue(defaultText), | Default-Wert |
WebPartStorage(Storage.Personal), | Unter eigenem Kontext speichern? |
FriendlyName("Text"), | Name der Property |
Description("Text Property")] | Beschreibung (Prosa) |
Das dwp-File sollte eine Konfigurationsdatei für das Web-Part sein. Properties können direkt über xml-Tags gesetzt werden. Man sollte universelle Web-Parts anstreben die über das dwp-File angepasst werden.
Verzeichnisse: C:\Inetpub\wwwroot\bin
CreateChildControls()
ICellConsumer.CellReady()
RenderWebPart()
Der Lebenszyklus, d.h. Reihenfolge der Event-Methodenaufrufe ist zwar grundsätzlich sinnvoll, bringt jedoch Probleme mit sich:
Alle Web-Controlls müssen in CreateChildChildControls()
instanziiert und der Control-Collection hinzugefügt werden, sonst feuern sie keine Events und behalten ihre Daten beim Postback nicht.
Click-Events werden erst NACH CreateChildControls()
ausgeführt. Um also auf einen Klick zu reagieren um z.B. ein Menü auszuklappen etc. müssen alle Controls instanziiert werden bevor man weiß welcher Menüpunkt ausgeklappt werden soll. Ein klassisches Henne-Ei-Problem.
Manchmal möchte man in einer Schleife Controls erzeugen, deren Anzahl von Listeneinträgen etc. abhängen. Das ist ein bißchen knifflig, es treten Henne-Ei probleme auf, insbesondere wenn das Web-Part ein Cell-Consumer (ein verbundenes Web Part, das einen Wert von einem anderen Web Part erhält) ist. Folgende Probleme treten auf:
CreateChildControls()
Methode müssen die Controls erzeugt und per Controls.Add()
hinzugefügt werden, damit die Werte persistieren und Events gefeuert werden. Zu diesem Zeitpunkt ist ein eventueller Cell-Consumer Wert noch nicht vorhanden, außerdem sind die Events noch nicht durchgelaufen.
RenderWebPart()
-Methode ist der Cell-Consumer Wert vorhanden und alle Event-Methoden wurden ausgeführt. Wenn die Controls jedoch hier erst instanziiert oder hinzugefügt werden, vergessen sie ihren Inhalt beim Postback, und zugewiesene Events werden nicht gefeuert.
visible=false
gesetzt sind, vergessen ihren Inhalt beim postback! (anders als in herkömmlichen ASP-Seiten!). Abhilfe: Controls auf unsichtbare DIV
-Tags setzen. Ist nicht sehr sauber, funktioniert aber. Siehe diesen News-Thread
...tbc...
In einem Webpart besteht in der Standardkonfiguration keine Session in der Daten abgelegt werden könnten. Man kann es allerdings im Page.Cache
Objekt tun:
Schreiben:
Page.Cache.Insert(string key, object value);
Lesen:
Page.Cache.Get(string key);
Damit man die Sharepoint standard CSS-Klassen (siehe CSS-Guide) in einem Webpart vernünftig benutzen kann muß die Eigenschaft UseDefaultStyles
im Konstruktor des Webparts auf false
gesetzt werden