SharePointCommunity
Die deutschsprachige Community für SharePoint, Microsoft 365, Teams, Yammer und mit Azure

Sponsored by

Willkommen im Forum Archiv.
Einträge sind hier nicht mehr möglich, aber der Bestand von 12 Jahren SharePoint-Wissen ist hier recherchierbar.




Property Bag Zentraladministration

Geprüfte Antwort Dieser Beitrag hat 16 Antworten

Ohne Rang
1714 Beiträge
C.Kaiser erstellt 25 Okt. 2010 16:46
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo zusammen,

ich würde gerne von einer normalen Sharepoint Webanwendung (port 80 usw.) Daten in den PropertyBag der Zentraladministration übergeben. Hintergrund ist, dass ich einen TimerJob gerne zentral aus einer SiteCollection heraus administrieren möchte und nicht aus der Zentraladministration heraus (die Site Collection Admins haben halt keinen Zugriff auf die Zentraladministration).

Für den normalen PropertyBag des Webs habe ich keine Probleme, aber wnen ich versuche in den PropertyBag der Zentraladministration zu schreiben, bekomme ich folgenden Fehler:
"There is no Web named "".   at Microsoft.SharePoint.Library.SPRequestInternalClass.GetWebMetainfo(String bstrUrl)
   at Microsoft.SharePoint.Library.SPRequest.GetWebMetainfo(String bstrUrl)"

Der Name des SPWeb-Objekts wird korrekt ausgelesen nur sehe ich beim Debuggen schon, dass der Fehler direkt unter "AllProperties" auftaucht - normalerweise stehn da ja alle Properties des Webs.

Kann mir da jemand helfen? :-) 

Alle Antworten

Ohne Rang
19231 Beiträge
Andi Fandrich Als Antwort am 25 Okt. 2010 17:10
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo Christian,

vor dem Problem stand ich auch schon und habe es dann mit SPPersistedObject gelöst.

Dazu legst Du eine Klasse abgeleitet von SPPersistedObject an. Die Klasse braucht einen public-Standardkostruktor. Bei allen Eigenschaften, die Du persistieren möchtest, markierst Du das zugehörige private Feld mit [Persisted]. Speichern geht wie gewohnt über Update().

Das eigentliche Handling geht über eine SPPersistedChildCollection<T> (T ist deine Klasse). Deren Konstruktor muß den Konstruktor der Basisklasse aufrufen, der wiederum ein SPPersistedObject entgegennimmrt. Das ist das Parent, z.B. SPFarm.Local. An ein bestimmtes Element der Collection kommst Du z.B. mit this.GetValue<T>(Guid).

Ich hoffe das hilft Dir erstmal.

Viele Grüße
Andi
af @ evocom de
Blog
Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 26 Okt. 2010 09:57
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo Andi,

danke schonmal! Werde ich heute im laufe des Tages testen :-)

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 27 Okt. 2010 12:51
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Ok habs jetzt auch nochmal hier nachgelesen:
http://www.c-sharpcorner.com/UploadFile/dhananjaycoder/sppersistedobjectclass11102009164419PM/sppersistedobjectclass.aspx

Wie komme / merke ich mir denn die GUID des persistierten Elements, wenn es aus einer anderen Webanwendung (Zentraladministration) und einer anderen Methode (TimerJob) aufgerufen wird? Da stehe ich gerade auf dem Schlauch...

Edit: Und wenn ich versuche ein Element zu persistieren, dann kommt ein Access Denied Error. Code läuft natürlich unter ElevatedPriviledges.

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
19231 Beiträge
Andi Fandrich Als Antwort am 27 Okt. 2010 13:12
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Das ganze Drumrum mußt Du natürlich selbst bauen. Ich kenne die Zusammenhänge für Deinen Fall ja nicht.

Man kann sich natürlich auch eigene Zugriffsmethoden bauen um z.B. alle Teile zu finden, bei der eine bestimmte Eigenschaft einen bestimmten Wert hat. So nach dem Motto GetByListId(...). Oder eben Du speicherst die Guid im PropertyBag einer Liste, damit Du das zugehörige Teil später leicht findest.

Edit:

[quote user="C.Kaiser"]Und wenn ich versuche ein Element zu persistieren, dann kommt ein Access Denied Error. Code läuft natürlich unter ElevatedPriviledges[/quote]

Das kann ich Dir nicht sagen. Funktioniert bei mir tadellos in mehreren Szenarien.

Viele Grüße
Andi
af @ evocom de
Blog
Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 27 Okt. 2010 13:46
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Ok danke schonmal für die Antwort... Ich glaub da muss ich mir was anderes überlegen, da ich die Anwendung später ausliefern muss und nicht weiß unter welcher URL dann meine Konfigliste mit der entsprechenden GUID liegt... Mal davon abgesehen, dass ich derzeit eh nichts weggespeichert bekomme :-)

Edit: OK Speichern im Farm.local PropertyBag funktioniert. dann werd ich den wohl nutzen.

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
643 Beiträge
Henning Eiben Als Antwort am 27 Okt. 2010 14:42
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Vielleicht eine Idee, was ich schon mal in einem anderen Projekt gemacht habe:

Ich habe aus einer Web-Anwendung einen TimerJob neu angelegt (per elevated-privilege). Dabei habe ich dem TimerJob die GUID der aktuelle Site (aus der ich den Job angelegt habe) mitgegeben. Ebenso die ID einer SP-Liste, in der sich Konfigurationsdaten befinden. Diese Daten habe ich per persistenter Properties am Timer-Job gespeichert.

Wird der Timer ausgeführt kann ich nun die GUID des Webs und der Liste nachschlagen und die Daten aus dieser Liste auslesen. Die Einträge der Liste können von der Web-Site aus manipuliert werden, so dass das Verhalten des Timers beeinflusst werden kann.

Henning Eiben
busitec.de

Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 27 Okt. 2010 17:40
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo Henning,

danke für den Vorschlag. Versuche ich aber aus einer Webanwendung ausserhalb der Central Administration einen TimerJob anzulegen, bekomme ich einen Access Denied Error, trotz ElevatedPriviliges.

Der gleiche Code funktioniert per Feature Receiver in der Central Administration aber eben nicht in einer anderen Webanwendung. In den Propertybag der Farm kann ich auch nicht speichern (wie ich gerade festgestellt habe), da bekomme ich auch den Access Denied Error.

Edit: Wenn die Webanwendung  unter dem Central Administration Anwendungspool läuft, gehts... Analog zu diesem Bug http://blog.thekid.me.uk/archive/2007/02/05/activating-office-sharepoint-server-publishing-infrastructure-access-denied.aspx

Hat da jemand im Kopf was da an meine Konfig falsch ist?

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
929 Beiträge
Thomas Östreich Als Antwort am 27 Okt. 2010 18:00
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

[quote user="C.Kaiser"]Versuche ich aber aus einer Webanwendung ausserhalb der Central Administration einen TimerJob anzulegen, bekomme ich einen Access Denied Error, trotz ElevatedPriviliges[/quote]

Das ist auch Richtig so das du ein Access Denied bekommst dann hast du schonmal deine Farm korrekt installiert / konfiguriert.

Die CA hat einen Application Pool und deine WebAnwendung hat einen Application Pool -> RunWithElevatedPriviliges macht nix anderes als die Ausführung unter dem Account des Application Pools, wobei der der CA im SqlServer mehr Rechte hat. Wenn nun mal in den SqlServer schaut sieht man, dass es dort auch die selben Accounts gibt, aber mit unterschiedlichen Rechten zu den einzelnen ContentDB's sowie der Konfigurations DB.

Schlußfolgerung TimerJobs können nur mit dem FarmAccount angelegt werden also -> du Benötigst ein WebApplication oder FarmFeature um TimerJob zu erstellen!

Jedes SPWeb hat einen PropertyBag was zum Speichern genutzt werden kann. Auf diese könnte dann ein allgemeiner TimerJob zugreifen und die geforderten Tätigkeiten anhand des PropertyBags der Site (SPWeb) ausführen.

Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 27 Okt. 2010 18:12
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Womit wir wieder bei meine Ausgangsfrage sind :-)

Wie bringe ich meinem TimerJob bei, welche Liste er verwenden soll... Ich kenne die zukünftige SiteCollection inkl. SPWeb-Objekt nicht, dass wird neu angelegt - dementsprechend kann ich es nicht hart in meinen Code reinschreiben. Jede SiteCollection inkl. Unterwebseite zu durchlaufen scheint mir doch ein mehr als großer Aufwand zu sein. Und die Konfigurationsseite des Timer Jobs soll nicht in die Zentraladministration, damit die SiteCollection Admins zukünftig den Timer Job selber "administrieren" / Einstellungen vornehmen sollen.

Andis Vorschlag mit SPPersistedObject funktioniert auch nicht, da die Content Webanwendung mit dieser Methode auch versucht in die Config-DB zu schreiben -> Access Denied.

Jetzt hab ich mich im kreis gedreht ... :-P

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
643 Beiträge
Henning Eiben Als Antwort am 27 Okt. 2010 18:32
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

OK, also noch 'ne Idee:

Du erstellst für die CA ein Feature, welches einen Web-Service bereitstellt. Dieser Dienst darf von außen verwendet werden (man kann ja noch irgendein Shared Secret mit einbauen, damit der Dienst nicht von jedem aufgerufen werden kann).

Dieser Dienst läuft also nun im Context der CA ab. Ansprechen kannst du den aber von jeder Web-App (mit entsprechendem Secret). Damit kannst du also aus der Web-App einen Job anlegen.

Henning Eiben
busitec.de

Ohne Rang
929 Beiträge
Thomas Östreich Als Antwort am 27 Okt. 2010 18:47
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

[quote user="Henning Eiben"]

Du erstellst für die CA ein Feature, welches einen Web-Service bereitstellt. Dieser Dienst darf von außen verwendet werden (man kann ja noch irgendein Shared Secret mit einbauen, damit der Dienst nicht von jedem aufgerufen werden kann).

[/quote]

Ich glaube nicht das der WebService von jeden aufgerufen werden kann, da ja integrierte Authentifizierung erforderlich ist. Wenn nun versucht wird mit einen Benutzer auf den WebService zu zugreifen muss dieser Account zugriff auf die CA haben -> Access Denied.

Ohne Rang
929 Beiträge
Thomas Östreich Als Antwort am 27 Okt. 2010 18:43
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Also ich habe es so wie oben schon gesagt gemacht:

1. Allgemeiner Timer Job (webApplication) per Feature bereitgestellt
2. WebSite oder SiteCollection Feature bereitgestellt was beim Aktivieren Abhängikeit zum WebApplication Feature hat (Kann die aber nicht aktivieren aber prüfen und darauf hinweisen das dies zu aktivieren ist bevor das Feature aktiviert wird)
3. Beim aktivieren im RootWeb der SiteCollection im PropertyBag einen Link zur WebSite hinzufügen (Guid) so das dann der Timer Job zu WebAnwendung nur in seine SiteCollections RootWebs schauen muss wo er tätig werden muss (collection von Guid's)
4. Diese alle dementsprechen instanzieren und aus den PropertyBag den Einstellungen Ermitteln aber das Dispose nicht vergessen

Anhand der Aktivierung auf WebAnwendungs ebene weist du auch wo deine SiteCollection's sind und musst nicht durch alle WebAnwendungen dich durch iterieren.

Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 28 Okt. 2010 10:08
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

OK Thomas, danke schonmal für die Hilfe, aber bei dem Punkt hier hänge ich gerade...

[quote user="Thomas Östreich"]

3. Beim aktivieren im RootWeb der SiteCollection im PropertyBag einen Link zur WebSite hinzufügen (Guid) so das dann der Timer Job zu WebAnwendung nur in seine SiteCollections RootWebs schauen muss wo er tätig werden muss (collection von Guid's)

[/quote]

Ich hab gestern Abend noch einen Denkfehler bei mir entdeckt...
- Ich habe den TimerJob immer unter der WebAnwednung der Zentraladministration aktiviert, dadurch war es denke ich mal klar, dass ich nicht weiter gekommen bin (jetzt läuft er unter der korrekten Content-Webanwendung).

Wie finde ich im TimerJob mein RootWeb der SiteCollections? SPContext gibt mir überall null - "this." (was ja denke ich den TimerJob repräsentiert) gibt mir als WebApplication die Zentraladministration zurück... Irgendwie fehlt mir da gerade noch der Durchblick.

Edit: Fehler (warum immer unter der Central Administration läuft) gefunden... Hab den Job falsch (immer unter der Central Administration) angelegt -> Übernahme von Code Snippets eines Kollegen *grml*

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
929 Beiträge
Thomas Östreich Als Antwort am 28 Okt. 2010 10:24
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Habe mal schnell nach SPTimerJob gesucht im Internet (1. Ergebnis) und das gefunden -> http://www.andrewconnell.com/blog/articles/CreatingCustomSharePointTimerJobs.aspx

Echt der Wahnsinn was man da so alles im Internet so findet und sollte genau für deine Sache funktionieren ;-)

Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 28 Okt. 2010 12:00
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Ja nicht ganz... die Guid die verwendet und mit dem TimerJob übergeben wird, entspricht bei mir nicht meiner Content-DB Guid.

Wie dem auch sei, mein Hauptfehler lag darin, dass ich den TimerJob beim anlegen immer an die Zentraladministration gehangen und so natürlich die falsche Webanwendung bekommen habe.

ich durchlaufe jetzt alle SiteCollections der übergebenen WebAnwednung und schaue in der RootWeb ob mein Flag vorhanden ist. Danach führe ich dann ganz normal meine Aktionen aus.

Danke nochmal für die Hilfe, war mein erster TimerJob und scheinbar muss ich bei allem, was ich mir neu aneigene erstmal sämtliche Fehler machen um ja auch den größten Lerneffekt zu gewährleisten.... ;-) Und ja ich hätte auch googeln können, allerdings hat der Job ansich ja funktioniert, nur bei der Anlage habe ich entsprechende Fehler gemacht ;-)

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
643 Beiträge
Henning Eiben Als Antwort am 27 Okt. 2010 18:29
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Ach ja, verdammt! Das war die Stelle die wir auch ausgenutzt hatten - bei uns waren für alle AppPools die gleich Accounts verwendet worden :) Es wollte sich bei der Installation ja keiner als "Information-Hider" outen!

Henning Eiben
busitec.de