Archiv der Kategorie: SharePoint

MindManager mit SharePoint verheiraten

Kürzlich haben wir für die IT das Tool MindManager von Mindjet lizenziert. Mehr zur Software und die Entscheidung diesbezüglich werde ich in einem späteren Blogeintrag thematisieren.

In dem vorliegenden Video zeige ich euch, wie ihr einige Unschönheiten im Zusammenspiel von MindManager und SharePoint Foundation 2010 in den Griff bekommt. Unter anderem wird ein entsprechendes Icon für mmap-Dateien eingebunden und das Öffnen der Dateien ermöglicht. Ist beispielsweise der Dateityp den Internet Information Services (IIS) nicht bekannt, kann die Map nur als ZIP-Datei heruntergeladen werden.

Weiterführende Links:

Advertisements

IT Asset Management mit SharePoint 2010 – Teil 1

Den Webcast dazu gibt es hier.

Der Aufbau der erwähnten Inhaltstypen habe ich als Screenshots eingefügt. Seht es eher als Beispielimplementierung, an der ihr euch orientieren könnt. Denkbar wäre z.B. eine Erweiterung dahingehend, dass ihr eine weitere Liste erstellt, in welcher ihr Systemausfälle samt Ursache, Lösung und Ausfalldauer notiert.

 

Überblick Inhaltstypen:

image

 

Inhaltstyp Server, welcher von Element ableitet:

image

Inhaltstyp Physical, welcher von Server ableitet:

image

Inhaltstyp Virtual, welcher von Server ableitet:

image

Inhaltstyp Serverlizenzen, welcher von Element ableitet:

image

Inhaltstyp Systeme/Dienste, welcher von Element ableitet:

image

 

Zusätzlich haben wir noch eine Liste mit den IT-lern und deren Verantwortungsbereich. Hier könnte aber durchaus auch auf eine bestehende Mitarbeiterliste, in welcher die mobile Geschäftsnummer hinterlegt ist, verwendet werden:

image

SharePoint Suche

Wenn die SharePoint Suche bei manchen Anwendern etwas anzeigt und bei anderen nicht, so könnte das Problem darin bestehen, dass das entsprechende Domänen-Objekt nicht korrekt konfiguriert ist. Im vorliegenden Fall war es so, dass die Kollegen aus dem Marketing keine Suchergebnisse im Wiki angezeigt bekommen haben, wir in der IT hingegen schon. Die Lösung stand in diesem Blogeintrag.

<<Lt. Doku muss man dem Search-Dienst User im Active Directory unter dem Reiter Sicherheit – bei Authentifizierte Benutzer das Recht "Lesen" zuweißen.>>

Inzwischen läuft alles problemlos…

Integration eines SharePoint Wikis ins ERP-System

Seit ca. 3 Monaten setzen wir erfolgreich auf die Kollaborationsmöglichkeiten, die ein Wiki-System bietet. Als Basis verwenden wir dazu die SharePoint Foundation, welche kostenlos für Windows Server zur Verfügung steht. In dem folgenden Video zeige ich, worauf es zu achten gilt und wie die Firma heco den Wiki Inhalt erfolgreich in das hauseigene ERP-System integriert hat.

In dem Video war leider keine Zeit mehr, um auf weitere Ideen einzugehen und weiterführende Quellen zu nennen, deshalb hole ich dies hiermit nach:

  • Geplant ist eine Ausweitung um Multimediainhalte, allerdings nicht nur aus SharePoint selbst, sondern auch von YouTube
  • Das Aufrufen von ERP-Funktionalität aus dem Wiki
  • Ein Webpart, welches automatisch die Daten des für den Inhalt zuständigen Sachbearbeiters lädt und anzeigt, z.B. die Telefonnummer

Für Rückfragen stehe ich gerne über die üblichen Kommunikationskanäle zur Verfügung. Aber auch wir haben noch Fragen: Kann mir jemand sagen, wo ich das Template für eine Wiki Seite anpassen kann, um z.B. auf allen Seiten immer den letzten Bearbeiter anzuzeigen oder um diverse Links immer am unteren Rand einzublenden?

 

Weiterführende Links:

Generische Factory

Heute will ich mal wieder aus einem Beispiel aus meinem Projektalltag ansprechen.

Es geht um Kalendereinträge in SharePoint. Wir haben 4 verschiedene Typen von Einträgen: Urlaub, Krank, Außer Haus, Im Haus. Im vorliegenden Fall müssen die Typen Urlaub und Krank exportiert werden. Generell ist es so, dass alle Typen bis auf 1-2 Felder die gleichen Eigenschaften besitzen. Ergo arbeite ich mit Vererbung. Die Base Class nennt sich CalendarEntry, von der die zwei Kindsklassen HolidayEntry und SicknessEntry erben (reine Data Transfer Objects).

Da ich die Daten untypisiert von SharePoint erhalte, habe ich mir eine generische Factory gebaut, die mir die 2 besagten Klassen instanziiert und füllt. Das Interface dazu sieht wie folgt aus:

   1: public interface ICalendarEntryFactory<T> where T:CalendarEntry, new()

   2: {

   3:     IEnumerable<T> Build(SPListItemCollection calendarEntries);

   4: }

Die implementierende Klasse enthält also eine Methode namens Build, die mir aus den Kalendereinträgen von SharePoint eine Liste von typisierten Objekten (IEnumberable deswegen, weil es allgemeiner ist als List<T>) zurückgibt. Um welche Objekte es sich handelt, die die Factory erzeugt, wird beim Instanziieren der Factory angegeben, allerdings habe ich den Objekttyp auf CalendarEntry oder eine Ableitung davon eingeschränkt (über where T:CalendarEntry in Zeile 1). Außerdem muss das Objekt (also mein DTO), welches die Factory später erzeugen können soll, einen parameterlosen, öffentlichen Konstruktor haben. Dies gewährleiste ich über das new() in Zeile 1.

Die Klasse, die nun dieses Interface implementiert, sieht wie folgt aus:

1: public class CalendarEntryFactory<T> : ICalendarEntryFactory<T>

where T : CalendarEntry, new()

   2: {

   3:     private readonly IRulesEngine<T> _rulesEngine;

   4:  

   5:     public CalendarEntryFactory(IRulesEngine<T> rulesEngine)

   6:     {

   7:         _rulesEngine = rulesEngine;

   8:     }

   9:  

  10:     public IEnumerable<T> Build(SPListItemCollection calendarEntries)

  11:     {

  12:         ...

  13:     }

  14: }

Noch kurz einen Hinweis zu dem Konstruktorparameter rulesEngine in Zeile 5: Da DTOs niemals Logik enthalten sollten und die Factory, wie der Name schon sagt, lediglich die Funktion erfüllt, dass es Objekte erzeugen kann, benötige ich noch ein Regelwerk, welches die erzeugten DTOs prüft, ob diese korrekt sind. Nur, wenn diese korrekt sind, werden sie der Liste, welche in der Build-Methode zurückgegeben wird, hinzugefügt. Meiner Meinung ist das sehr sinnvoll, um eine stärkere Code Kohäsion zu erhalten. Das entspricht auch den Clean Code Prinzipien Single Responsibility Principle und Seperation of Concerns. Die RulesEngine ist wie man sieht ebenfalls generisch gehalten. Logischerweise mit dem gleichen Typparameter T!

Ein Beispiel, was ich unter anderem mit der RulesEngine prüfe: Ist der Urlaubseintrag vom Typ JAZ (= Jahresarbeitszeit, ohne näher zu erklären, was JAZ bedeutet), so handelt es sich um einen Eintrag, der nicht in das Lohnprogramm exportiert werden darf.

Aber zurück zu der Build-Methode, die mir generisch die Objekte erzeugen soll: Da die Objekte teilweise unterschiedliche Eigenschaften haben (nämlich die, die in den ableitenden Klassen selbst definiert sind), muss ich in der Build-Methode eine Fallunterscheidung machen. Der Code sieht wie folgt aus:

   1: var entriesResult = new List<T>();

   2: T entry;

   3:  

   4: foreach (SPListItem calendarEntry in calendarEntries)

   5: {

   6:     entry = new T();

   7:  

   8:    foreach (SPListItem calendarEntry in calendarEntries)

   9:    {

  10:         //erledige Zuweisungen, die bei allen Eintragstypen gleich sind

  11:  

  12:         if (entry.GetType().Equals(new HolidayEntry().GetType()))

  13:         {

  14:             //erledige spezielle Zuweisungen für den Eintragstyp Urlaub

  15:         }

  16:         else if (entry.GetType().Equals(new SicknessEntry().GetType())) {

  17:             //erledige spezielle Zuweisungen für den Eintragstyp Krank

  18:         }

  19:  

  20:         //erledige Anweisungen, die bei allen Eintragstypen gleich sind

  21:         if (_rulesEngine.Validate(entry)) entriesResult.Add(entry);

  22:    }

  23: }

 

In Zeile 6 sieht man, warum ich bei meinem generischen Constraint dieses “New()” angegeben hatte: Ich muss zur Laufzeit von dem Typ, für den die Factory instanziiert wurde, ein Objekt erzeugen können. Die eigentliche Problematik tritt auf, wenn man die Fallunterscheidung durchführen will (Zeile 12 und 16):

Eine Prüfung auf den Namen des Typs wollte ich nicht durchführen, das ich dann den Namen hardcodiert als Zeichenfolge hätte hinterlegen müssen. Deshalb Instanziiere ich mir in den Zeilen 12 und 16 ein leeres Objekt und hol mir dessen Typ. Der Vorteil ist, dass Refactoring Tools und natürlich auch der Compiler das erkennen. Statt der If-Else-Verschachtelung wollte ich eigentlich eine Switch-Anweisung nehmen (macht natürlich v.a. dann Sinn, wenn man viele solcher Typen hat), allerdings ist hier das Problem, dass der Compiler eine Konstante in den Case-Anweisungen erwartet. Das ist leider nicht gegeben, da ja erst zur Laufzeit bekannt ist, was “entry.GetType()” eigentlich ist.

Peter Hallam, Entwickler bei MS, hatte den Hintergrund dazu bereits 2005 gebloggt. Das macht natürlich Sinn, dass man kein switch auf einen Typen anwenden kann.

Wer allerdings keines der genannten Szenarien aus zuvor erwähntem Blogeintrag bei sich in der Anwendung vorliegen hat, kann sich die Klasse aus dem Blogeintrag switching on types hernehmen, sodass er nicht mit if-else-Verzweigungen arbeiten muss.

Factory Method Design Pattern

Ich konnte kürzlich das Factory Method Pattern schön im Kontext der Web/SharePoint Entwicklung einsetzen, als eine Klasse ihre SPWeb Abhängigkeit per Constructor Injection reingereicht bekommen sollte. Hier die zwei Samples dazu:

   1: public class Sample1

   2: {

   3:     private SPWeb _web;

   4:     public Sample1(SPWeb web)

   5:     {

   6:         _web = web;

   7:     }

   8: }

   9:  

  10: public class Sample2

  11: {

  12:     private Func<SPWeb> _web;

  13:     public Sample1(Func<SPWeb> webFactory)

  14:     {

  15:         _web = webFactory;

  16:     }

  17: }

Während in Sample1 immer das gleiche Objekt für Aufrufe auf dem SPWeb-Kontext verwendet wird, ist es bei Sample2 so, dass man jedes Mal ein neues SPWeb Objekt erhält und darauf seine Abfragen ausführt.

Das hat in diesem Szenario primär den Vorteil, dass ich in Sample 2 mit Using arbeiten könnte, sodass die Methode, die das SPWeb Objekt verwenden will, sich selbstständig um das disposen kümmern kann. Das ist gerade bei Web/SharePoint Anwendungen wichtig, da Microsoft hier kaum Interfaces anbietet, die man bei UnitTests verwenden kann. Dementsprechend muss man sich eigene Interfaces und Wrapper-Implementierungen bauen, die man mocken kann. Allerdings würde das bedeuten, dass das aufrufende Objekt des Fakes sich um den Lifecycle der Fake-Abhängigkeiten kümmern muss, was sehr lästig ist. Für die konkrete Implementierung sähe das natürlich nicht anders aus…

Auf folgender Seite findet ihr noch eine sinnvolle Anwendungsmöglichkeit: http://www.dofactory.com/Patterns/PatternFactory.aspx#_self2

Wikipedia kann euch weitere Details zu dem Pattern nennen.

Die Gefahr bei Twitter Webparts

In meinem vorherigen Beitrag habe ich auf ein Twitter Webpart verwiesen, welches man zur Anzeige der Tweets im Intranet verwenden kann. Im Live-Betrieb ergab sich nun das Problem, dass durch die vielen Zugriffe der Account immer wieder für 1h gesperrt wurde. Jedenfalls ist das meine Vermutung. Es war dann nicht mehr möglich per externer App wie z.B. Tweetdeck, Seesmic oder eben dem Webpart auf den Account zuzugreifen. Lediglich über die Twitter Homepage konnte man sich noch anmelden. Das ist insofern seltsam, als dass im Twitter Support steht, dass dies auch nicht mehr möglich sein dürfte. Außerdem handelte es sich nicht um fehlerhafte Login-Versuche seitens des Webparts, sondern um erfolgreiche. Bei einer hohen Zahl gleichzeitiger falscher Logins würde ich es verstehen, wenn der Account gesperrt wird, um Hacker Angriffe zu unterbinden.

To make a long story short: Verwendet dieses Webpart, dann habt ihr das Problem nicht. Der Unterschied ist der, dass hier lediglich die Suchfunktion von Twitter selbst verwendet wird. Es findet keinerlei Zugriff auf das eigentliche Konto statt (erkennbar daran, dass keine Zugangsdaten bzw. Keys in den Webpart-Einstellungen eingegeben werden müssen).

%d Bloggern gefällt das: