Monday, December 19, 2011

WebPart targeting feature con User Profile e custom con IRuntimeFilter2


Nel paradigma delle Intranet 2.0 gioco un ruolo importante la personalizzazione dei contenuti. Sintetizzando il concetto possiamo dire che gli utenti devono essere in grado di navigare una intranet ottenendo contenuti personalizzati. Quali sono i criteri di personalizzazione? Sicuramente un ricco profilo utente può essere un'ottima fonte di informazioni per definire un audience, ma non è l'unica fonte dati. L'appartenenza a gruppi potrebbe essere di interesse per individuare classi di profilo. Talvolta sono necessario delle logiche personalizzate che si basano su dominio, nome utente o informazioni contenuti in altri sistemi (ad esempio sistema di HR).

Calando il requisito su SharePoint troviamo una funzionalità che fa il caso; è il targeting e può essere applicato ad interi contenuti (item in generale) o parti di un contenuto (webpart). Il targeting viene presentato come un campo con il picker che ne permette la selezione di audience, distribution list e sharepoint group. 

Con l'amico Carmelo abbiamo appronfondito gli internals. La configurazione di SharePoint richiede che per usare la funzionalità dei targeting sia necessario configurare la User Profile Service Application e associarla alla web application tramite il proxy; senza la USPA associata alla web application, non viene visualizzata la proprietà della webpart Target Audience all'interno della ToolPart.



Il sistema del targeting è implementato a basso livello e questo ne per permette l'applicazione sulle webpart senza richiedere specifici sviluppi.
Queste caratteristiche fanno si che il targeting sia disponibilie sono sulla versione Server e non quella  Foundation. 

Qui è nata la mia curiosità e l'approfondimento di questo post. Domande tipo "è possibile fare uso del targeting anche senza UPSA?" o "se le formazioni delle audience sono contenuti sui gruppi SharePoint perchè dobbiamo necessariamente fare uso della USPA?" o "sono ammesse logiche custom per l'assegnazione della audiences?"

Il principale indagato era un componente che viene istanziato in tutte le webpart, la cui configurazione è salvata sul web.config nella chiave SharePoint/RuntimeFilter. Sto parlando di questa chiave

La classe Microsoft.Office.Server.Audience.AudienceManager implementa le interfacce IRuntimeFilter (ormai obsoleta) e IRuntimeFilter2 usata dal WebPartManager per valutare se il sistema di filtro delle webpart debba essere valutato e utilizzato, e ne influenza la visualizzazione all’interno della Toolpart. Ho verificato che commentando questa chiave le webparts non visualizzando più il campo Target Audiences.

Facendo qualche ricerca ho trovato che componente era già presente su di Microsoft.SharePoint.Portal, Version=11.0.0.0 (naturalmente al tempo non c'erano ancora le service application); il sistema ha quindi un punto di estendibilità e permette di implementare custom runtime filter per andare ad gestire i filtri sulle webpart. Ne parla approfonditamente il libro SharePoint 2010 Web Part in Action di Wictor Wilén (SharePoint MVP e MCM) dedicando appunto un capitolo all’implementazione di un custom filter

"The runtime filter in SharePoint is a specific class derived from the IRuntimeFilter2 interface. This class is registered in the web.config file and is called for every Web Part when rendering a page. A specific method in the class tells SharePoint whether it should be shown to the user. In this section you’ll create a custom runtime filter that can be used to target the Web Part using the site collection groups. This will give you the option to target Web Parts to specific groups even in SharePoint Foundation."

Thursday, December 15, 2011

Ottenere la versione di SharePoint


Ottenere la versione della build di SharePoint 2010 è un operazione estremamente semplice, ma ... ci sono dei ma.

Il metodo migliore per ottenere la versione è quello di aprire la Central Admin e nella sezione System Settings accendere alla voce Manage servers in this farm (http://site/_admin/FarmServers.aspx).


Per avere delle informazioni di dettaglio su tutti i componenti installati (es. language pack) si può andare su Upgrade and Migration e selezionalare Check product and path installation status (http://server/_admin/PatchStatus.aspx)



In entrambe i casi è comunque necessario fare accesso alla Central Admin. Ci sono alternative?

Se abbiamo accesso al SQL Server che ospita il database della Central Admin e si ha a disposizione SQL Management Studio, questo script TSQL ci restitusce la build number.
SELECT Version, UserName
FROM Versions
WHERE VersionId = '00000000-0000-0000-0000-000000000000'
ORDER BY Id DESC

Se possiamo fare girare del codice su server SharePoint si può creare una console application che estrae le stesse infomazioni.
using (SPSite startSite = new SPSite("")) {
   SPFarm farm = startSite.WebApplication.Farm;
   SPWebService service = farm.Services.GetValue("");  
   foreach (SPWebApplication webApplication in service.WebApplications) {
      foreach (SPSite site in webApplication.Sites)   {
         Console.WriteLine(string.Format("{0} - {1}", site.Url, site.ContentDatabase.Name)); 
      }
   }
}

Naturalmente questi metodi devono essere eseguiti con un utente che abbia i diritti appropriati. Se non avessimo questi diritti? Se fossimo abilitati ad accedere ad una site collection con una security più limitata? Per farla ancora più difficile: da un sito di publishing pubblicato su internet e acceduto in modalità anonima possiamo identificare la build installata?
La risposta è sì, ma ... non è detto che il dato ottenuto sia "sempre" affidabile.

Per ottenere la versione si deve analizzare il contenuto delle HttpResponse generate da SharePoint  e tra gli header troveremo uno dal nome MicrosoftSharePointTeamServices. Questo header è configurato su IIS da SharePoint 2010 e mantenuto aggiornato dai vari  aggiornamenti di SP e CU.



Via Javascript possiamo così scrivere alcune righe di codice per risalire dalla build.
var xmlHttp = new XMLHttpRequest();
var url = "http://yoursite"; 
xmlHttp.open('HEAD', url, false);
xmlHttp.send();
var SPVersion = xmlHttp.getResponseHeader("MicrosoftSharePointTeamServices");

NOTE: talvolta gli IT Admin considerano che l'esposizione di questo tipo di informazioni possa in qualche modo 'ledere' la sicurezza della farm. Il ragionamento è "se chiunque è in grado di ottenere informazioni sul livello di Patch, la stessa persona potrebbe attaccare la piattaforma sfruttando le vunerabilità conosciute". Di fatto però la maggior parte dei siti internet ospitati su SharePoint espongono questa informazione ... provare per credere!


UPDATE 15/1: ovviamente anche via Powershell con l'addin di SharePoint 2010 otteniamo la build tramite (Get-SPFarm).BuildVersion