SlideShare une entreprise Scribd logo
1  sur  107
Télécharger pour lire hors ligne
UNIVERSITÀ DEGLI STUDI DI TRIESTE 
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010 
Dipartimento di Ingegneria e Architettura 
Corso di Laurea Magistrale in Ingegneria Informatica 
Laureando: 
Relatore: 
DOTT. ALEX RONCI 
DOTT. ING. MAURIZIO FERMEGLIA 
Correlatore: 
DOTT. DARIO SOTTANA 
ANNO ACCADEMICO 2013 - 2014
2 
Ad Ornella, Antonello e Thomas
3 
1 Introduzione 
La tesi proposta all’interno di questo documento tratta la progettazione e la programmazione di una struttura di appoggio per gli sviluppatori definita come framework di sviluppo utile alla generazione di un sistema informativo in ambiente CMS (Content Management System) Microsoft SharePoint Server 2010 con cui dare l’opportunità di esulare dall’utilizzo base della struttura di workflow, un modello per la pianifica strutturata di processi programmati, proposta ed implementata dall’azienda di Redmond. 
Commisionataria del progetto è l’azienda Reply SpA – Cluster di Trieste. 
L’interesse dell’azienda è quella di avere una struttura più flessibile rispetto quella proposta dalla Microsoft: difatti, come descritta sul loro sito ufficiale, “Workflow is sometimes described as a series of tasks that produce an outcome. In the context of Microsoft SharePoint Products and Technologies, workflow is defined more narrowly as the automated movement of documents or items through a sequence of actions or tasks that are related to a business process”; a quanto si evince, la possibilità di far fluire il materiale a disposizione in maniera non lineare non è contemplata nelle intenzioni originali della piattaforma SharePoint. 
Questo fatto ci porta ad optare per una soluzione custom che permetta uno scorrere libero lungo tutte le fasi del processo produttivo che si andrà ad implementare nella site collection di interesse. L’obiettivo della tesi dunque risulterà implementare, all’interno di una feature adeguabile ad ogni circostanza similare, un workflow personalizzato a fasi, accompagnato da tutti quei metodi, form ed elementi che possano risultare utili ad un corretto e semplificato sviluppo di una site collection nell’ambiente di riferimento per uno sviluppatore futuro. 
L’importanza non sarà dunque solamente quella di fornire un prodotto che permetta di scorrere nel processo produttivo, ma che funga primariamente da framework orientato ad agevolare la scrittura di codice da parte di un programmatore che andrà a referenziare tale libreria nella sua soluzione, in modo tale che non debba perdere tempo nello sviluppo di articolati metodi ripetitivi, come possano essere quelli di un passaggio fase, un ritorno ad una fase precedente, alla gestione dei permessi od alla creazione automatizzata di elenchi di servizio interno.
4 
Pur nella vastità del progetto, gli elementi che verranno trattati all’interno di questa tesi saranno alcuni di questa libreria, con un occhio particolare su: 
a) Metodi e classi per lo sviluppo delle funzioni di utility: lo sviluppo di tutte quelle funzionalità base da fornire allo sviluppatore per agevolare il compito di scrittura del codice. Fornire una gamma di metodi più e più volte richiamati all’interno dell’ambiente di sviluppo può portare ad un grosso vantaggio in termini di tempo, e di uniformità di invocazione e gestione di accessi, creazione, modifica delle strutture fornite da Sharepoint. 
b) Sviluppo logico del workflow: lo sviluppo di una soluzione custom per lo scorrimento in avanti ed indietro nel processo produttivo, tenendo sotto controllo la gestione e controllo dei permessi sugli oggetti coinvolti. Fornire una gestione logica e standardizzata dell’applicazione è importante per semplificare al massimo il lavoro dello sviluppatore che utilizzerà tale framework, e dunque è fondamentale sviluppare le proprie componenti in maniera che siano comprensibili ed adattabili alle più svariate situazioni, rendendole il più possibile generiche. 
c) Esempi: A completamento del progetto, verranno presentati alcuni casi di implementazione di quello che è stato sviluppato nei punti precedenti, in modo tale da rendere l’idea di come produttivamente possano essere utili le librerie sviluppate. 
Ovviamente gli elementi che verranno implementati all’interno delle libraries sono possibilmente molti di più, ma probabilmente possono risultare meno interessanti di quelli che sono stati citati, perché meno personalizzati oppure meno salienti rispetto l’obiettivo verso cui protende la tesi stessa, ma sono utili per poter far funzionare appieno tale feature. 
1.1 Perché Microsoft SharePoint Server 2010 
La scelta di approfondire il progetto in un ambiente professionale come quello di SharePoint Server 2010, piuttosto che la corrispettiva piattaforma Foundation oppure un utilizzo più visuale come quello fornito da SharePoint Designer, è dovuta al fatto di poter operare su di un prodotto più approfonditamente modificabile ed alterabile, in cui un’interfaccia a codice (nel caso di SharePoint C#) possa permettere di intervenire più in profondità sulle strutture di interesse.
5 
Da un breve confronto ed analisi dei pro e contro dei vari ambienti di sviluppo, difatti, si può ritenere che la possibilità di personalizzazione di SharePoint può essere così tracciata: se con un utilizzo base, direttamente da interfaccia web, uno sviluppatore (o meglio, in questo caso sarebbe più corretto indicare un utente “collaboratore”) potrebbe andare a caratterizzare approssimativamente un cinquanta per cento delle potenzialità della Site Collection sviluppata, e con il crescere delle capacità e conoscenze ad un circa sessantacinque, solo approdando in un ambiente adeguato (come per esempio SharePoint Designer) potrebbe ottenere dei risultati che si avvicinino al massimo del potenziale. Servono assolutamente degli ambienti di sviluppo (IDE) adeguati (ed in questo caso la migliore è quella fornita direttamente di Microsoft con Visual Studio) e una profonda conoscenza del linguaggio di sviluppo, in modo tale da avvicinarsi prepotentemente alla completa gestione delle potenzialità del CMS. 
Questo è l’obiettivo ultimo di tale tesi: avere un prodotto più possibilmente performante e generico che possa essere integrato nella maggior parte dei progetti di interesse dell’azienda commisionataria, in modo tale da poter agevolare e alleggerire il carico lavorativo dello sviluppatore, fornendo un framework di supporto nelle più comuni necessità di integrazione tra l’ambiente default fornito da Microsoft e quello personalizzato e maggiormente pertinente al tipo di attività svolte dall’azienda. 
Il documento qui presente risulterà, in conclusione, diviso in tre parti fondamentali: 
 Nella prima sezione, verrà trattato il nuovo sistema di workflow, descrivendone le caratteristiche mantenute dalla versione Microsoft e le soluzioni custom proposte in questa tesi, tracciandone principalmente la sua struttura logica e dandone una prima applicazione in produzione caratterizzando le possibili strutture da implementare; 
 La seconda sezione, quella più corposa, andrà a trattare la composizione della library di metodi che andrà a far da fondamenta per il framework obiettivo di tesi, descrivendone l’architettura e le funzionalità attribuitele, e descritti i metodi forniti al suo interno (con, in alcuni casi, approfondimenti sul flusso logico delle operazioni svolte); 
 La terza sezione, invece, andrà a fornire un esempio di applicazione delle aree precedenti, con un’analisi del connubio delle varie fasi operative del workflow ed il framework stesso, rendendo così pratica l’applicazione della teoria proposta nei capitoli precedenti
6 
Nella parte finale del documento, invece, verranno indicate le possibili espansioni del framework sviluppato, e nelle appendici verranno approfonditi alcuni interessanti temi che vadano a motivare o a esplicare alcune operazioni trattate durante l’intero sviluppo del testo.
7 
2 Workflow 
La prima parte del progetto è quella preposta ad analizzare e sviluppare una struttura di workflow che vada a sopperire alle mancanze, dal punto di vista dell’azienda commissionataria, di quella proposta da Microsoft. 
2.1 Breve definizione 
Il workflow1 è la descrizione di una sequenza di operazioni di un lavoro attribuito ad una persona od ad un gruppo, all’interno di un meccanismo di step che si susseguono senza ritardi uno dopo l’altro, e spesso viene trattato come un’astrazione del lavoro reale, o come rappresentazione di quest’ultimo. 
Più correttamente, quello che viene esplicitato da noi è quello che viene definito Workflow Management System, un sistema informatico che gestisce ed organizza una serie di tasks per restituire in uscita il risultato del processo produttivo, anche se risulta più semplice definirlo workflow. 
Gli elementi da tenere in considerazione all’interno di un’attività di un workflow sono: 
1. Input: tutte quelle che sono le informazioni necessarie al completamento dello step; 
2. Gli algoritmi e le azioni da svolgere, a livello umano o a livello macchina, per completare lo step; 
3. Output: tutte quelle informazioni che verranno passate al completamento dello step stesso. 
2.2 Workflow in SharePoint 
Rispettando le linee guida che vanno a definire il flusso, SharePoint2 propone delle soluzioni lineari, orientate all’organizzazione efficace di ruoli e task attivi all’interno del processo, in modo tale da garantire la riduzione ai minimi termini di delay durante i passaggi di consegne, adattandosi al genere di flusso dati richiesto all’interno dell’organizzazione interessata. 
Come rimarcato anche dalla definizione, il workflow mantiene una struttura lineare e unidirezionale, come esplicitato dai flussi proposti di default in SharePoint: 
1 https://en.wikipedia.org/wiki/Workflow 
2 http://technet.microsoft.com/library/cc263148(office.14).aspx#WFlowOverview
8 
 Raccolta commenti e suggerimenti; 
 Approvazione; 
 Approvazione dell’eliminazione; 
 Raccolta firme; 
 Tre fasi; 
 Gestione traduzioni; 
 Gestione problemi. 
Vi è la possibilità di introdurre dei workflow dichiarativi (quelli descritti in precedenza) oppure compilati, con l’aggiunta di codice personalizzato; tutti conducono ad un flusso ordinato di dati. 
2.3 Requisiti 
Il tipo di workflow richiesto in questo processo ha delle peculiarità: 
 Possibilità di scorrimento all’indietro nel flusso, in opportuni casi, svincolandosi dalla rigidità del workflow classico; 
 Organizzazione dei task in macrofasi, di cui è possibile modificarne i contenuti nel momento in cui vi si trova al suo interno. 
Per l’implementazione, viene lasciata totale libertà di scelta delle strutture su cui far poggiare il flusso in SharePoint, senza richiedere vincoli di utilizzo di DBMS particolari o strutture particolari. 
Inoltre, viene richiesto di consegnare tutta una serie di funzionalità, metodi che ne permettano un’implementazione efficace all’interno del CMS.
9 
Figura 1 - Task 
2.4 Specifiche 
I due requisiti proposti sono legati l’un l’altro, poiché possono permettermi di operare all’interno di un ambiente di workflow pur modificandone parzialmente la logica. 
Il concetto di task è considerabile come un insieme atomico di azioni da compiere per portare un item dallo stato A allo stato B 
E le modifiche apportate, giunti nello stato B, risultano permanenti, senza permettere dunque la possibilità di ritornare ad A. 
Le modifiche da proporre sono dunque legate alla gestione del task ed al susseguirsi logico delle attività da svolgere all’interno del workflow: si è scelto di procedere secondo le logiche descritte in seguito per implementare queste modifiche. 
2.4.1 Gestione delle macrofasi 
Se si vogliono introdurre delle macrofasi, o macro attività, all’interno del workflow, rimandendo coerenti con il suo funzionamento logico, c’è la necessità di stravolgere il concetto di task in quanto tale. 
Il task non può essere trattato come unità atomica, ma come sequenza di microtasks interni che si susseguono, e comunicanti tra loro i contenuti raccolti nella loro azione. 
Se ne volessimo fare una raffigurazione grafica, questo sarebbe descrivibile in tal maniera: 
Figura 2 - Macro Task
10 
La struttura avrebbe dunque: 
 Ingresso al task dall’esterno (freccia arancione in ingresso); 
 Uscita dal task sia a livello logico (freccia arancione da Task C), sia a livello di dati (freccia gialla da Dati), con unica uscita output. 
preconfigurandosi, almeno alla visione esterna, con la struttura di una classica attività di workflow. 
Le modifiche sostanziali sono all’interno: 
 I dati vengono divisi dalle attività; 
 Scindendo contenuti e processi, posso suddividere le operazioni in micro-attività, mantenendo condivisi i contenuti fino a quel momento inseriti; 
 Ogni micro attività avrà a disposizione tutti i dati raccolti nei micro task precedenti, permettendone l’edit di questi, oltre a quelli di pertinenza della fase in questione; 
 Su ogni micro task, essendo considerati essi stessi task, avranno diritto di azione ruoli diversi (se necessario); 
Il flusso descritto dalle frecce arancioni traccia il percorso dello stato del workflow, mantenendone l’ordine logico anche all’interno del macro task e marcandone la struttura, mentre quelle gialle tracciano il flusso dei dati raccolti, mostrando come i contenuti siano condivisi all’interno della macro fase, e siano accessibili in lettura e scrittura a seconda dello step in cui vi si trovi. 
L’attività opera in tal maniera: 
1. Il workflow entra nel macro task, come se si trattasse di una comune attività; 
2. Vengono definiti i ruoli del primo micro task; 
3. L’utente incaricato opera sui dati che può operare nello step in cui si trova; 
4. Completata l’operazione, vengono spostati i dati all’interno dell’area condivisa e vengono trasferiti i ruoli all’utente di pertinenza; 
5. L’utente subentrante ha la possibilità di operare sui dati vecchi sia su quelli inerenti al suo step; 
6. Completata l’operazione, si reitera da 4, finchè non si completano tutti gli step interni;
11 
7. Arrivati all’ultimo step, escono sia i dati che lo stato di fase, in modo tale da restituire un valore unico all’attività successiva. 
Il task così definito può andare a sostituire logicamente quello classico all’interno del flusso, poiché non va ad intaccarne la teoria alla base: se ne mantiene l’orientamento, ma ci permette di operare in istanti diversi su dati che possono essere già stati inseriti in precedenza, senza dover abortire il processo. 
Il workflow assumerà dunque questa possibile nuova forma: 
2.4.2 Gestione del rollback di uno step 
Secondo passo da analizzare è quello del ritorno ad uno step precedente, concetto non contemplato nella teoria dei workflow. 
Le problematiche di questo tipo di processo sono dovute a: 
 Conservazione dello stato del task: se torno indietro, dove mi trovo? 
 Conservazione dei dati: se torno indietro, i dati inseriti in step successivi dove vanno a finire? 
 Permessi: se torno indietro, ho ancora accesso agli step successivi, o solamente alla fase in cui si è tornati? 
 Ruoli: chi ha la possibilità di fare il rollback? 
Dalla discussione di queste tematiche possiamo ottenere una possibile risposta alla richiesta. 
Figura 3 - Esempio di Workflow personalizzato
12 
2.4.2.1 Stato del task 
L’operazione di rollback non deve essere evidente ad una visione esterna del flusso, questo per i soliti motivi asseriti nella teoria dei workflow. 
Quindi deduciamo che la risposta sia: se vi è una rollback, per il workflow devo trovarmi comunque nello stato precedente, così da ovviare a problematiche di gestione e comprensione del flusso stesso. 
2.4.2.2 Stato dei dati 
La conservazione dei dati nel caso di rollback è di articolata gestione, poiché il passaggio da una fase N ad una N-1 comporta 
1. Cambiamento dei dati ricevuti in input da N-1; 
2. Possibile cambiamento dei dati in input da N; 
3. Possibile incompatibilità dei dati inseriti in precedenza in N con i nuovi di N-1 
Proponiamo qualche esempio pratico: 
 In fase N-1 ho inserito un documento, e i dati al suo interno determinato le operazioni della fase N; se torno in fase N-1, ho la possibilità di sostituire tale file, e di conseguenza condizionare le operazioni di N; 
 Nella fase N respingo i contenuti di N-1, consentendo, con il rollback, la sostituzione di questi ultimi. Avrebbe senso conservare i dati (negativi) di N tornando in fase N-1? 
 In N eseguo alcune operazioni, ma verifico l’incompletezza (o l’inesattezza) dei dati passati da N-1; se le operazioni svolte in N non sono toccate dalle correzioni, ha senso non conservare i dati fino a lì raccolti? 
 Se in N-1 ho la possibilità di fare un rollback anch’esso per N-2, dovrei avere condizioni di verifica tali da poter verificare che le sostituzioni possibili in N-2 non abbiano effetto su N-1 e dunque su N. 
L’elemento di cui tenere primariamente conto dunque è la possibilità di intaccare la correttezza e la consistenza dei dati raccolti dallo step N-m (con m numero di rollback) a N (fase effettivamente raggiunta). 
Dunque la risposta presa in considerazione è: non risulta efficace conservare i dati delle fasi successive se vi è stato un rollback, per evitare rischi di correttezza dei dati già acquisiti. Le
13 
occasioni di avere dei dati non condizionanti, all’interno di workflow, sono molto poche, dunque è difficile che non vi sia incidenza di un task in quello successivo. 
2.4.2.3 Permessi 
La possibilità di operare indistintamente tra più fasi successive può creare dei problemi similari a quelli descritti nel punto precedente: la correttezza del dato resta comunque un cardine di qualsiasi processo informatico, e consentire operazioni parallele su contenuti che possono condizionarsi vicendevolmente può essere pericoloso. 
Dunque la possibile soluzione è quella di non concedere l’accesso alle operazioni consentite in una fase N, nel caso in cui si torni in una N-1, per le stesse motivazioni date nel paragrafo precedente. 
2.4.2.4 Ruoli nel rollback 
Altro frangente da tenere in considerazione è il tipo di utenza che può operare il rollback del task. Questo deve coincidere con l’utente stesso che ha diritto di operare sul task stesso oppure posso concedere dei permessi speciali ad un utente esterno e sorvegliante il workflow? 
Consentire l’interazione di utenze esterne all’interno di un task di non propria competenza andrebbe in contrasto con il flusso previsto nella teoria dei flussi: l’utenza opera unicamente sui task di propria competenza. 
Si possono dunque generare dei task di approvazione dei dati, in modo tale da scindere il rollback dal concetto di approvazione del dato inserito da altre utenze. 
La risposta a quest’ultimo punto può essere quindi negativa, non consentendo utenti con poteri di rollback esterni a quelli già aventi diritto di processo su di un determinato task. 
2.4.3 Definizione delle specifiche 
Dall’analisi dei punti precedenti, la specifica che ne possiamo trarre fuori avrà questi vincoli: 
 Il rollback verrà introdotto unicamente all’interno dei macro task descritti in 2.4.1: come illustrato dalle frecce rosse, il flusso all’indietro all’interno del macrotask non genera problemi, per via dei dati condivisi e del non variare dello stato del flusso complessivo del workflow.
14 
Figura 4 - Rollback in Macrotask 
 Il rollback non sarà consentito a cavallo di task non appartenenti allo stesso macro 
task, per non intaccare la consistenza dei dati; 
 Il rollback annullerà tutti i dati inseriti nelle fasi successive a quelle in cui ci si trova, per 
evitare problemi di consistenza dei dati; 
 Il rollback inibirà l’accesso a tutte le operazioni di fasi successive a quella in cui ci si trova: se torno dal task C al task B, non avrò modo di operare sul task C finchè non avrò nuovamente concluso il task B; 
 Il rollback non sarà consentito ad utenze che siano esterne a quelle che ne hanno diritto; non è contemplato un utente supervisore che condizioni il flusso. 
Figura 5 - Rollback tra task diversi 
Annulla Dati di fase 
Figura 6 - Eliminazione dati con Rollback
15 
Il flusso conserverà tutti i suoi crismi originali, e il nostro lavoro dunque si concentrerà sulla gestione dei macro task e sulla rispettiva strutturazione in ambiente SharePoint, esulando dalla struttura di default proposta da Microsoft. 
2.4.4 Specifiche accessorie 
Oltre a comprendere quali siano le soluzioni per i due requisiti, è importante definire e comprendere quali siano le specifiche di contorno utili al progetto: 
1. Interfacce che permettano la visione globale e precisa di workflow ed istanze di queste; 
2. Nel caso di istanze di workflow, elementi di gestione di flusso tra le varie fasi, sia in caso di passaggio tra fasi interne ad un macrotask, sia nel caso di flusso da un task ad un altro, quali ad esempio pulsanti complementari a quelli di default; 
3. Possibilità di visionare ed editare i dati di fasi precedenti interne al proprio macrotask senza che questi si mescolino / non siano evidenti all’interno del task di propria competenza. In tal maniera abbiamo una descrizione a tutto tondo di quello che ci servirà per definire e rendere il workflow comprensibile e gestibile all’utente finale. 
Task completato 
Task in esecuzione 
Rollback Task C 
A 
B 
C 
A 
B 
C 
A 
B 
C 
Task A completato 
Completo task B 
Task non eseguibile 
Figura 7 - Inibizione di accesso a dati futuri con Rollback
16 
2.5 Progettazione 
Basilare è scegliere come organizzare il workflow, definendo su quale delle possibili strutture dati gestire il flusso. Allora sarà da specificare come implementare lo scorrimento tra le fasi e tutto ciò che va a circondare questi processi. 
2.5.1 Gestione dei dati nelle macrofasi 
Lo step è trovare una struttura logica che ci permetta di gestire la condivisione delle informazioni tra task successivi ed appartenenti alla stessa macrofase. Non è possibile gestire nelle modalità proposte da un workflow classico, poiché i dati caricati in precedenza sarebbero accessibili solo per approvazione, e non in edit (tornando cioè alla conformazione di task distinti e non aggregati). 
L’ipotesi che si va a proporre dunque contempla una gestione condivisa dei dati stessi, tramite un insieme (ipotizzabile in forma tabulare) aggregato di informazioni suddiviso per sottoaree, accessibili a seconda del task in cui ci si trova. 
Con una rappresentazione grafica, si può ipotizzare un frammento all’interno di una macrofase in questo modo descritto: 
In tale modo l’utente del task avrà almeno accesso in lettura ai dati delle fasi precedenti, se non addirittura in scrittura (dipende dal ruolo dell’utente coinvolto), potendo dunque gestire e motivare il rollback (ad esempio, correzione dei dati inseriti in precedenza), ed allo stesso tempo operare su dati inseriti in precedenza senza arrecare inconsistenza nei dati. 
Dati Task A 
Dati Task B 
Dati Task C 
Task A 
Task B 
Task C 
Figura 8 - Dati condivisi in macrotask
17 
2.6 Scelta della struttura dati 
La struttura, tra quelle disponibili in SharePoint, più similare a quella proposta, anche se può sembrar banale, è quella della lista. Questo perché: 
 È un insieme ordinato di oggetti in cui si può accedere alle varie colonne in modo guidato, tramite le form; 
 Permette di avere un aggregato dei dati della macrofase, associato in modo univoco ad un item, che è il nostro flusso; 
 Posso relazionare più liste (e dunque più macro task) tra loro inserendo un identificativo univoco e condiviso tra le varie liste, in modo tale da tenere traccia dell’evoluzione del flusso. 
 Posso inserire un parametro di fase, che mi identifichi in quale stato si trovi il macrotask al momento del salvataggio, in modo tale da poter gestire di conseguenza i permessi associati all’item. 
Scegliere un’altra struttura, come ad esempio quella della Document Library, rendere il tutto decisamente più complicato a livello di organizzazione: 
 Sarebbe da organizzare una folder della DL per ogni flusso interessato, e le relative subfolder create ad ogni passaggio di macrotask, cosa che invece con un insieme di liste (già definito) porterebbe alla sola aggiunta di un item con identificativo univoco già creato; 
 Problemi sui permessi: ogni volta che creo una cartella dovrei configurare i permessi su essa e poi su tutti i suoi contenuti, non avendo un parametro di controllo facilmente condivisibile; 
 Problemi nella ricerca: dovendo attingere a delle cartelle, non ho la certezza di avere i dati di cui sono interessato (potrebbero essere in eccesso o mancarne alcuni); 
 Problemi nel confronto dei dati: dovendo pescare da folder distinte, dovrei fare un’analisi gerarchica all’interno di queste, verificando fino a che punto si sia giunti, per poi raccogliere i dati; nel caso di una lista, vedo direttamente tramite una view quello che mi interessa; 
 Gestione dei requisiti: Organizzo delle subfolder nelle subfolders? Avrei dei problemi a sul piano del macrotask (i documenti non sarebbero condivisi, aprendo criticità a livello
18 
di permessi). Organizzo tutto in una cartella comune? Avrei problematiche nella distinzione dei file nelle varie microfasi; 
Allo stesso modo, l’introduzione forzata di una struttura come i Document Set risulterebbe maggiormente articolata (la banale installazione della feature associata costringerebbe ad avere una site collection compatibile con quest’ultima) e non così efficace rispetto a quelli che potrebbero essere i profitti: anche in questo caso ci troveremmo di fronte ad una struttura atta a gestire documenti, non tanto a dati, riportandoci ai problemi definiti per la Document Library. 
Dunque, la strutturazione del workflow a macrofasi tramite liste risulta essere la soluzione più efficace e completa per le nostre finalità: potremo apprezzare nei capitoli successivi come questa via risulti adeguata.
19 
3 Library SharePoint Utilities 
La seconda sezione del nostro progetto va a trattare il package che va a fornire le funzioni di estensione più comuni per il tipo di progetti creati nell’azienda, e di appoggio al workflow trattato nel capitolo precedente. 
L’obiettivo primario è quello di fornire metodi utili ed efficaci al futuro programmatore in modo tale che non debba scrivere del codice ripetuto, ripetitivo e spesso utilizzato all’interno di un qualsiasi progetto. 
Rispettando un concetto di chiarezza e semplicità all’interno del package, è importante anche suddividere il prodotto sin dall’interno in feature, per mostrarne le diverse funzionalità e permetterne l’utilizzo distinto a seconda dei casi. 
Essendo un modulo di generics, è molto utile poter far scegliere al programmatore quali funzionalità importare all’interno del proprio progetto, consentendo una scelta che non vada ad inibire l’utilizzo di una o l’altra funzionalità. Oltretutto, la creazione di un numero maggiore di feature consente una migliore gestione del debugging, poiché rende possibile ridurre le problematiche ad un pacchetto più piccolo e più facilmente controllabile. 
3.1 Requisiti 
Il prodotto, in questa parte del progetto, deve soddisfare le richieste del workflow, dunque consentire la gestione di: 
 Gruppi Utenti 
 Document Libraries 
 Liste di Configurazione 
 Elenchi 
 Mail 
A cui, inoltre, associare la configurazione di WebPages all’interno dell’ambiente SharePoint, la gestione degli accessi in modalità di manutenzione della piattaforma in utilizzo, e fornire tutti i possibili metodi di supporto per un corretto funzionamento dei metodi richiesti.
20 
3.2 Analisi funzionale 
L’organizzazione logica della solution è già descritta dalle specifiche. Si necessita dunque di due features separate, pur appartenenti allo stesso prodotto, per lo sviluppo del software e per la gestione della manutenzione della site collection. 
Per l’area di sviluppo, i requisiti indicano aree di sviluppo (sei) distinte tra di loro: la soluzione più ovvia e mantenere questa configurazione pure all’interno della feature, consegnando una classe per ogni tipologia di componente da implementare. 
Si è dunque andati a definire sei classi che si distinguano per i metodi forniti: 
1. DocLib per la gestione delle document libraries; 
2. Groups per la configurazione dei gruppi; 
3. KeyValList per le liste di configurazione; 
4. Lists per la creazione di liste; 
5. Mailer per fornire i servizi di mail al workflow; 
6. PubManager per le pagine di pubblicazione da interfaccia 
A questi dunque sono stati associati quei metodi comuni e necessari in ogni loro situazione. Primariamente sono state dunque considerate 4 classi accessorie, che vanno a vertere su due tematiche distinte, le security e il logging, e importate con queste modalità: 
Figura 9 - Strutturazione funzionale della library
21 
Il principio alla base delle classi accessorie si mantiene lo stesso di quello utilizzato nelle altre classi: assegnarne una per categoria di funzionalità permette di distinguere immediatamente ciò che viene fornito, semplificando allo sviluppatore la comprensione della struttura a disposizione. 
Per l’area di manutenzione, invece, i requisiti indicano una sezione di controllo degli accessi alle operazioni disponibili. 
L’idea proposta è quella di introdurre un prefiltraggio alle pagine a cui accedere, nel caso in cui la feature sia attivata. 
Proporre dei metodi, in questo caso, può risultare inefficace, poiché sarebbe poi da trovare delle modalità per far passare tutte le pagine in prefiltraggio per questi, costringendo gli sviluppatori ad inserire una chiamata al metodo in un qualsiasi Page Load, non sempre disponibile oltretutto. 
Si può preferire dunque la creazione di un ascx che funge in forma delagata all’apertura di ogni pagina, così da inserire un controllo in questo preciso istante: questo va ad alleggerire il carico sullo sviluppatore, che può completamente dimenticarsi la gestione di tale frangente, ed occuparsi unicamente della scrittura del codice inerente alle funzionalità della pagina di interesse. 
Questa feature dunque sarà configurata in modo tale da fornire al solo gestore della site collection ed agli amministratori la possibilità di attivare questa funzione (anche perché sarebbero gli unici interessati ad averne accesso), e dunque attivabile per via interfaccia a seconda della situazione. 
Quello che si va ad ottenere, e che andremo a descrivere in seguito, è dunque una struttura con due feature, le Utilities e la BlockUsers, attivabili in maniera distinta e indipendenti l’una dall’altra, cosicchè ogni site collection abbia la possibilità di scegliere se attivare o meno tali funzionalità fornite. 
3.3 Feature Utilities 
La prima feature sviluppata comprendere gli effettivi metodi di utilities che vanno a soddisfare i requisiti di questa porzione di progetto.
22 
3.3.1 Classi 
3.3.1.1 DocLib 
La classe DocLib contiene quei metodi che vanno ad essere di supporto alla generazione delle Document Libraries di nostro interesse. Al suo interno sono stati sviluppati, al momento, 5 metodi “principali”, con alcuni metodi accessori di controllo. 
3.3.1.1.1 SPList Create 
Questo metodo va a generare una Document Library all’interno del site di interesse. Ha come parametri di input questi argomenti: 
o SPWeb web: è l’url del WebSite di interesse 
o String name: è il nome da associare alla Document Library 
o String description: è la descrizione da associare alla Document Library 
o Boolean? displayOnQuickLaunch: è il valore di controllo per far visualizzare la Document Library sulla Quick Launch Bar del WebSite. 
Il diagramma di flusso del metodo è molto semplice: 
Figura 10 - Flusso SPList Create
23 
Il percorso illustra come gli argomenti di input influiscano direttamente sul procedere dello stesso. Importante è avere definiti entrambi i parametri per eseguirne correttamente il list.add all’interno del WebSite, che va a restituire la GUID della lista creata, su cui poi poter configurare la property di visibilità nella quickLaunch. 
Il list ed il web Update vanno a consolidare le modifiche svolte, a chiusura del metodo, restituendoci la lista stessa come output. 
Nel caso di malfunzionamento, il metodo va in catch e da un log di report. 
3.3.1.1.2 Void MoveAttFile 
Questo metodo permette il trasferimento di un documento da una Document Library ad un’altra. Gli argomenti in input sono: 
o SPWeb web; 
o String listName: è il nome della Document Library da cui attingere; 
o String oldStringUrl: è il percorso da dove proviene il documento da trasferire; 
o String fileName: è il nome del file da trasferire; 
o List<String> folderListLevel: è l’elenco delle folder del percorso per giungere alla folder in cui spostare il documento; 
o Boolean forceElevatedPrivileges: permette, a seconda del valore settato, di operare o no con i permessi da amministratore; 
o Out String url: è l’url di uscita del file trasferito 
Il metodo va a richiamarne un altro omonimo, con gli stessi input (tranne la gestione dei permessi elevati), che esegue il processo vero e proprio: 
1. In un boolean viene salvato lo stato dell’AllowUnsafeUpdates; 
2. Lo stato del web.AllowUnsafeUpdates viene settato a false, per poter operare senza problemi questo processo di trasferimento; 
3. Viene richiamato il metodo EnsureFolders per verificare che il path assegnato sia realmente esistente, dandocene l’url (lo approfondiremo nella descrizione del metodo stesso); 
4. Viene recuperato l’SPFile tramite l’oldFileUrl;
24 
Figura 11 - Flusso insertFile 
5. Tramite il metodo dell’oggetto MoveTo, quest’ultimo viene spostato nel nuovo path con il fileName assegnato; 
6. Viene generato l’url definitivo, che verrà poi restituito come output del metodo; 
7. Viene ripristinato lo stato iniziale dell’AllowUnsafeUpdates. 
Anche in questo caso viene configurato un try / catch in modo tale che possa intercettare gli errori di inserimento dei file nelle varie cartelle, verificando l’unicità di tale documento e l’effettiva trasferibilità dello stesso. 
3.3.1.1.3 Void InsertFile 
In maniera similare al precedente, questo metodo va a creare un file all’interno della Document Library di interesse. Gli argomenti del metodo sono: 
o SPWeb spWeb; 
o String listName; 
o Stream fileStream: è lo stream del contenuto del documento da creare; 
o String fileName;
25 
o Boolean overwrite: bool per la gestione della sovrascrizione dei file con stesso fileName nella stessa lista; 
o List<String> folderLevelList; 
o Boolean appendNewGuid: bool per assegnare un nuovo GUID all’oggetto che si va a creare; 
o Out String url. 
In questo caso, dopo aver configurato o meno i permessi elevati per creare il file, viene anche effettuato l’overload di tale metodo, andando a seguire il flusso nella figura precedente. 
Il risultato è quello di salvare l’url relativo del file appena creato all’interno della variabile url, consegnatoci funzionante dal try / catch di controllo; nel caso di malfunzionamenti, verrà generata un’eccezione e restituito un url vuoto. 
3.3.1.1.4 Void DeleteFile 
Al contrario del metodo precedente, questo andrà a rimuovere il file indicato. Come parametri di input avrà difatti, oltre al classico spWeb, l’url del file e il boolean forceElevatePrivileges. 
A seconda del forceElevatedPrivileges, il metodo accederà o no in un SPWeb con i privilegi da amministratore, per poi fare un spWeb.GetFile(url) e rimuovere questo. 
3.3.1.1.5 Metodi di controllo 
A supporto dei metodi descritti in precedenza, abbiamo tre metodi di controllo dei file names ed uno per il controllo del path di destinazione dei file. 
3.3.1.1.5.1 File Name 
Questi tre metodi servono a ripulire i nomi dei file che verranno caricati a livello programmatico all’interno di Lists e Document Libraries, in modo tale che queste ultime possano accettarli senza avere alcuna generazione di errore. Il fatto di non aver errori a livello di caricamento di file creati è fondamentale per poter evitare documenti rotti o spezzati. 
3.3.1.1.5.1.1 Boolean CheckLengthFileName 
Verifica la lunghezza della stringa in input. Restituisce true se la lunghezza di tale è minore di una costante definita nella classe.
26 
3.3.1.1.5.1.2 Boolean checkFileName 
Verifica la correttezza del nome del file, controllando l’assenza di caratteri speciali all’interno della stringa in input. Restituisce true nel caso venga superato il controllo. 
3.3.1.1.5.1.3 String CleanFileName 
Ripulisce il filename dai caratteri non ammessi, nel caso vi fossero, e accorcia la lunghezza del file ad un valore pari alla costante definita nella classe, in modo tale da essere caricabile all’interno delle strutture di interesse. 
3.3.1.1.5.2 Path 
Il controllo sul percorso in cui andare a inserire è importante quanto la corretta definizione del nome del file stesso. Cercare di mettere un documento all’interno di uno spazio non esistente apporterebbe degli errori non indifferenti, primariamente nella creazione ed inserimento del documento stesso, poi perché andrebbe ad inficiare sul flusso dei dati di nostro interesse. 
Per questo motivo è stato sviluppato il seguente metodo. 
3.3.1.1.5.2.1 Void EnsureFolders 
Questo è il metodo di appoggio più interessante, poiché va a verificare l’esistenza delle folder del percorso del file che si andrà a creare (spostare), in tal modo da aver effettivamente una folder in cui porre quest’ultimo. 
Il diagramma di flusso del metodo è quello descritto nella pagina successiva.
27 
3.3.1.2 Groups 
La seconda classe che verrà analizzata è quella dei gruppi: all’interno di questa sono stati implementati tutti quei metodi che portano alla creazione, eliminazione e verifica dei gruppi all’interno della site Collection di nostro interesse. 
3.3.1.2.1 SPGroup Create 
Il metodo va a creare un nuovo gruppo all’interno della Site Collection, segnalando errore nel caso, ad esempio, questo già esista. Non è necessario l’accesso con permessi elevati, poiché tali operazioni si presume possano essere utilizzate unicamente da utenze già abilitate con tali ruoli. 
Gli argomenti di input sono: 
o SPWeb spWeb; 
Figura 12 - Flusso ensureFolders
28 
o String spGroupName: Il nome da assegnare al gruppo; 
o String spGroupDescription: la descrizione del gruppo; 
o SPMember groupOwner: l’owner del gruppo che si va a creare; 
o SPRoleDefinition spRoleDefinition: il ruolo assegnato di default al gruppo all’interno della Site Collection. 
Il flusso del metodo è così descrivibile: 
Allo stesso modo, vi è un metodo in overload che invece di prendere il parametro SPRoleDefinition ha come argomento un SPRoleType: questo richiama il Create con 
spRoleDefinition = spWeb.RoleDefintions.GetByType(roleType) 
3.3.1.2.2 void CreateIfNotExistsPermissionLevel 
Il metodo qui descritto va a verificare l’esistenza di un livello di permessi da poter assegnare, in seguito, ad un determinato gruppo: se questo non esistesse, verrà creato. 
Argomenti richiesti sono: 
o SPWeb spWeb; 
Figura 13 - Flusso SPGroupsCreate
29 
o String permissionLevelName: il nome del livello di permessi che si intende verificare; 
o String permissionLevelDsc: la descrizione del livello, nel caso se ne creasse uno nuovo; 
o SPRoleType: il ruolo associato a questo livello, nel caso se ne creasse un nuovo 
Il codice è di per sé particolare: sfruttando il try / catch come se fosse un if, nel caso non esistesse il tipo di permesso associato al permissionLevelName, all’interno del catch sia andrà a definire quest’ultimo, con nome, descrizione e ruolo. In caso di funzionamento corretto, non verrà eseguito alcunchè. 
3.3.1.2.3 Void FindGroupToDeleteToCreate 
Questo metodo accessorio permette di restituire un elenco (nuovo) di gruppi da eliminare e di popolare un’altra list con quelli da creare, verificando tra quelli già esistenti. 
Input del metodo sono: 
o SPWeb spWeb; 
o SPGroupCollection spGroupCollection: è la collezione di gruppi da controllare; 
o Ref List<String> newGroupNameList: l’elenco dei gruppi da aggiungere (è una lista già preesistente passata dal processo invocante) [è fondamentale che questo elenco sia ordinato alfabeticamente]; 
o Out List<String> spGroupListToDelete: è l’elenco dei gruppi da rimuovere; 
Il metodo controlla di non aver già analizzato per intero i contenuti della collection di gruppi spGroupCollection e la lista dei nomi newGroupListName. 
Se così fosse, entra in un secondo ciclo while che confronta i nomi dei gruppi presenti. Il compare dei nomi serve proprio a questo: nel caso il gruppo seguisse nell’ordine un gruppo già presente, visto l’ordinamento alfabetico di entrambe le liste, andrebbe ad implicare l’inutilità del gruppo sopra citato, e dunque avente diritto ad entrare immediatamente nelle liste da cancellare. 
Nel caso invece i due nomi coincidessero (dunque il compare tra newGroup e spGroup risultasse pari a 0), il newGroup non sarebbe da aggiungere, e dunque andrebbe rimosso dall’elenco dei nomi “nuovi”.
30 
Ad ogni passaggio viene verificato che la collection spGroupCollection abbia un valore maggiore a quello del suo counter (sennò finirebbe immediatamente il processo in atto); superati i while, dunque, avremmo le liste popolate in maniera da avere i gruppi non esistenti da una parte, quelli da rimuovere dall’altra. A completare il ciclo, vengono verificati gli ultimi Gruppi che non siano stati confrontati: questi stessi verrebbero spostati nella lista dei gruppi da rimuovere, e mandato dunque, alla fine del for, il processo in chiusura. Il diagramma di flusso è: 
Figura 14 - Flusso FindGroupToDeleteToCreate
31 
Come sottolineato, l’ordinamento alfabetico è trascendentale per il corretto funzionamento del metodo: se andassimo ad operare su di un elenco non ordinato, il metodo di controllo si sfalderebbe al primo gruppo non ordinato, e dunque andremmo a rimuovere gruppi da mantenere oppure ad aggiungere gruppi già esistenti, andando incontro ad un’inevitabile crash. 
3.3.1.2.4 Boolean hasCurrentUserAPermissionLevel 
Il metodo in questione verifica se un determinato utente ha almeno un livello di permessi all’interno della site Collection presa in considerazione, e torna true nei casi in cui soddisfi questa richiesta, oppure sia siteAdmin. 
Questo metodo poggia su di un altro presente in questa classe, il isPermissionLevelInRoleAssignment (che verrà descritto in seguito), ed ha come parametri di input il classico spWeb e l’elenco di string permissionLevelsName di cui verificare la presenza. 
In questo caso, per poter verificare i permessi, necessitiamo di un accesso con privilegi Elevati. 
Il metodo si comporta in questo modo: 
1. Viene settato a false il valore da mandare come output del modulo; 
2. Viene creata una chiave per tutti i gruppi che contengono lo user preso in considerazione, e la metto all’interno del dictionary groupUserHasAccess; 
3. Viene creato l’ambiente per operare con i privilegi elevati; 
4. Si verifica se è admin della site Collection: se si, ritorna true; 
5. Se non passa la verifica, viene generata una spGroupCollection dei gruppi presenti sulla site Collection, ed un SPRoleAssigmentCollection dei permessi presenti sulla stessa; 
6. Per ogni gruppo della spGroupCollection viene lanciata una query linq in cui si verifica se vi è un record che appartenga alla dictionary e che abbia lo stesso Group.ID; 
7. Se sì, si verifica il gruppo abbia uno dei livelli permessi elencati all’interno del permissionLevelsName: in caso affermativo, setto il valore di output a true e faccio un return di quest’ultimo; 
8. Nel caso non risultasse alcun permesso associato ai gruppi, vi sarebbe un’ulteriore verifica, tramite il metodo isPermissionLevelInRoleAssignment, rispetto al singolo
32 
utente: con lo stesso ragionamento proposto al punto 7, se verrà riscontrato almeno uno dei permessi richiesti, verrà ritornato true; 
9. Nel caso si giungesse a questo punto, il metodo ritornerà false. 
Il tutto permetterà di ovviare a dover passare per via di interfaccia alla scansione dei permessi di un utente all’interno di una site Collection. 
Allo stesso modo, è stato implementato un ulteriore metodo in overload che, oltre a restituire il booleano, rende in out l’elenco dei gruppi in cui lo user ha i permessi ricercati. 
3.3.1.2.5 Boolean isPermissionLevelInRoleAssignment 
Quest’ultimo metodo della classe ci permette di verificare se un RoleAssignment contiene uno dei RoleDefinitionBindings presenti all’interno della lista di permessi passata in input. Presi come argomenti: 
o SPRoleAssigment spRoleAssigment: è il ruolo da verificare 
o String[] permissionLevelsName: è il nome dei permessi da verificare 
Verranno estratti i livelli di permesso associati all’spRoleAssigment, e per ognuno di questi attuato un compare del loro nome con le stringhe: in caso affermativo, il metodo restituirà true.
33 
3.3.1.3 KeyValList 
La terza classe in oggetto è quella che consente una generazione rapida di liste di Configurazione da associare alla site Collection, generando, di principio, una lista strutturata come un dictionary con key e value. 
I metodi di questa classe risultano fortemente correlati tra loro: dunque, per agevolare la comprensione di questi, non verrà seguito un ordinamento alfabetico, ma piuttosto verrà seguito, dal basso verso l’alto, l’ordine di incapsulamento di questi, descrivendo quelli che poi verranno richiamati all’interno degli altri. 
3.3.1.3.1 Bool TryAddKey 
Il metodo in oggetto va ad aggiungere un nuovo item nella lista di nome listName con chiave key e valore value. I parametri di ingresso sono: 
o SPWeb spWeb; 
o String listName; 
o String key; 
o String value; 
Il metodo esegue una query linq all’interno della lista, e verifica che non vi sia già un item con key identica a quella passata. In conclusione, il flusso sarà il seguente: 
Figura 15 - Flusso TryAddKey
34 
3.3.1.3.2 void CreateKeyValueListNoPrivileges 
Questo metodo permette la generazione effettiva della Lista di Configurazione all’interno della propria site Collection, con la generazione della stessa in caso di necessità, e di popolamento tramite il dictionary passato. 
Argomenti del metodo sono: 
o SPWeb web; 
o String listName; 
o Dictionary<String,String> keys: è l’elenco di chiavi da inserire all’interno della lista; 
o KeyValueListPermissions permissions: è il tipo di permessi da assegnare alla lista 
Quest’ultimo type è generato appositamente per la classe in questione, permettendo la gestione dei permessi in modalità ereditata dall’ambiente oppure Admin only. 
La funzione verifica se la lista di configurazione non sia già esistente, tramite l’utilizzo particolare del try/catch, e dunque va ad inserire, nella lista esistente (o creata dal metodo stesso) il dictionary passato in input, controllandone l’univocità dei parametri passati. 
Questo va ad esplicitare il funzionamento del try / catch: nel caso di non esistenza della lista, la funzione andrebbe in errore, ma il catch, come da corretto funzionamento, cattura questo scatenando la creazione della lista stessa ed andando a popolarlo di conseguenza. 
La pulizia dei permessi tramite il tipo KeyValueListPermissions permette inoltre di tutelare i contenuti della lista stessa da modifiche indesiderate da parte di utenze in teoria non abilitate. 
Il diagramma di flusso è dunque il seguente:
35 
Figura 16 - Flusso CreateKeyValueListNoPrivileges 
3.3.1.3.3 Void CreateKeyValueList 
Questo è il metodo che va a richiamare il precedente per poter funzionare. Ricevendo come input: 
o SPWeb web; 
SPList spList = web.Lists[listName] 
try 
Visitata tutta la dictionary 
Log dell’add riuscito 
TryAddKey 
Generazione della Lista di Configurazione 
noCrawl = true 
spDefaultView.ViewFields.Add(VALUE_FIELD_NAME) 
try 
Visitata tutta la dictionary 
Add dell’item 
Permissions = ONLY_SCA 
Rimuovi tutti I permessi sulla lista 
Log di errore di creazione 
VERO VERO FALSO FALSO CATCH E CATCH E FALSO FALSO VERO VERO
36 
o String listName; 
o Dictionary<String,String> keys; 
o KeyValueListPermissions permissions; 
o Boolean forceToElevatePrivileges 
Questo prepara, a seconda del valore di forceToElevatePrivileges, l’ambiente in cui invocare il CreateKeyValueListNoPrivileges, passando come parametri quegli stessi ricevuti come argomenti alla rispettiva invocazione, senza operarne alcuna modifica. 
3.3.1.3.4 String GetValueFromKeyNoPrivileges 
Seguendo la strutturazione dei metodi precedenti, questo va ad essere il “nucleo operativo” dell’operazione di ricerca della key e di restituzione del rispettivo value. 
Ricevendo come argomenti: 
o SPWeb web; 
o String listName; 
o String key: è il parametro della chiave da ricercare; 
o Out SPListItem item: è l’item su cui salvare la ricerca. 
Questo pesca la key in questione all’interno della lista definita con listName, passa l’item ritrovato in out e restituisce il value dell’item stesso. 
3.3.1.3.5 String GetValueFromKey 
Come il metodo CreateKeyValueList, quest’ultimo prepara l’ambiente per invocare il GetValueFromKeyNoPrivileges, a seconda del bool che riceve in argomento: 
o SPWeb web; 
o String listName; 
o String key; 
o Out SPListItem item; 
o Boolean forceToElevatePrivileges. 
Allo stesso modo esiste un metodo overload senza l’argomento out SPListItem: in questo caso ne viene generato uno in locale e passato come argomento per invocare il metodo GetValueFromKeyNoPrivileges.
37 
3.3.1.3.6 Void SetOrAddValueNoPrivileges 
Ricevendo come parametri di ingresso: 
o SPWeb web; 
o String listName; 
o String key; 
o String value 
Questo verifica (tramite query linq) se è già presente un item con quella key, ne crea uno se non esistente, e dunque setta il valore del campo VALUE con quello passato in ingresso. 
3.3.1.3.7 Void SetOrAddValue 
Come per i metodi precedenti, anch’esso genera l’ambiente con o senza privilegi elevati per eseguire il SetOrAddValueNoPrivileges. 
3.3.1.4 Lists 
Questa quarta classe ha un comportamento e dei metodi similari a quelli proposti all’interno della DocLib class, poiché invece di operare su di una Document Library, operiamo su di una Lista, che, dal punto di vista di SharePoint, risultano essere delle strutture similari tra loro. 
Prima di iniziare a descrivere i metodi, è da analizzare la classe introdotta al suo interno, per il tipo Field, utile per la gestione del tipo di campo da inserire in una lista. 
3.3.1.4.1 Class Field 
Questo type è costituito da 4 properties e due costruttori, così definiti: 
 SPFieldType Type: definisce il tipo di campo da inserire nella lista; 
 Bool Required: impostazione dell’obbligatorietà sul campo; 
 Bool AllowMultipleValues: configurazione della possibilità di più valori per il campo in questione; 
 String[] Choice: i possibili valori associabili al campo stesso 
I costruttori invece si differenziano nella gestione dei campi AllowMultipleValue e Choice: 
1. Il primo costruttore definisce le possibili choices all’interno dell’oggetto 
2. Il secondo definisce se è possibile un valore multiplo per lo stesso
38 
3.3.1.4.2 SPListItem CopyItemTo 
Questo metodo permette la copia di un item da una lista ad un’altra che abbia almeno i campi di questo già definiti al suo interno. Come argomenti abbiamo: 
o SPListItem item: è l’item da copiare; 
o SPList destinazione: è la lista di destinazione; 
o SPFolder allegati: è la cartella che comprende gli allegati da copiare 
Il metodo opera in questo modo: 
1. Viene creato un nuovo item nella lista di destinazione 
2. Per ogni field all’interno dell’item, viene verificato che non sia un readOnlyValue, non sia un campo calcolato e non sia uno dei campi built-in delle liste di SharePoint, e verifica che un campo con quel nome esista effettivamente 
3. Se supera il test al punto sopra, inserisce il valore all’interno del campo di pertinenza, e ripete 2. finchè non ha verificato tutti i campi dell’item; 
4. Per ogni attachment passato, ne recupera l’oggetto fisico (tramite l’url dell’item di origine); 
5. Ne apre un array di byte; 
6. Lo allega all’item nuovo, e ripete da 4 per tutti gli attachments; 
7. Rimuove tutti i permessi del nuovo item; 
8. Prelevando i ruoli dall’item di origine, li trasferisce al nuovo; 
9. Per tutti gli allegati dell’SPFolder li trasferisce associandoli all’item stesso; 
10. Restituisce il nuovo item. 
3.3.1.4.3 SPListItem MoveItemTo 
Il metodo opera in maniera similare al precedente. Unica differenza è l’eliminazione dell’item di origine alla fine della funzione. 
3.3.1.4.4 SPList Create 
Consente la generazione, in modalità diverse, delle liste. È un metodo in overload, con 4 signature diverse. Argomenti in comune sono: 
o SPWeb web; 
o String name: il nome della lista da creare
39 
Mentre a differire è il modo in cui vengono passati i tipi di campo all’interno della lista stessa: 
1. Dictionary<String,Fields> fields 
Dopo aver creato una nuova lista generica con il nome passato in input, viene analizzato il dictionary in tale modo: 
È importante notare che i campi SPFieldChoice e SPFieldUser debbano avere un percorso stante a se stesso poiché sono gli unici che richiedono dei parametri particolari (le possibili choices in un caso, l’AllowMultipleUser nell’altro) da inserire. Gli altri necessitano unicamente, nel nostro interesse, del solo nome di campo, il tipo dello stesso ed il boolean per la configurazione dello stato required. 
2. List<SPFields> fields 
In questo caso i campi sono già strutturati, perché la lista riceve dei tipi di campo. Dunque la funzione si riduce ad aggiungere alla vista il campo e configurarne il suo tooltip, definendone la possibilità di visualizzazione in tutte le possibili form della lista stessa. 
Tutte le complicazioni illustrate in 1. non vi sono poiché i campi non devono essere creati ex- novo. 
Fields[nomeCampo].type 
SPFieldChoice scelta 
Choice != null 
Aggiungi scelte possibili 
SPFieldUser user 
MultiUser == true 
Consenti MultiUser 
Aggiungi alla lista 
Aggiungi alla lista con i parametri necessari 
Aggiungi il campo alla vista di default 
Tipo SPFieldChoice Tipo SPFieldUser Altri Tipi VERO VERO FALSO 
Figura 17 - Flusso Create
40 
3. String contentTypeId, SPListTemplateType listType 
Con questa signature l’idea è quella di permettere la generazione di una lista con template di base definito dall’utente e settarne il relativo content type tra quelli disponibili. Il content type permette di definire il metedata ed il behaviour per un determinato data entity, a cui sono associati i relativi workflow, policy, site columns.3 
Il metodo opera in tale maniera: 
i. Viene generata la lista; 
ii. Per la lista viene abilitata l’associazione dei content types (list.ContentTypesEnabled); 
iii. Viene creata un elenco toDelete dei content types da rimuovere recuperando tutti quelli già associati alla lista stessa; 
iv. Viene generato un nuovo Content type definito tramite la stringa contentTypeId; 
v. Vengono rimossi tutti i content types dell’elenco toDelete associati alla lista in questione 
Come oggetto in uscita abbiamo la lista stessa creata 
4. String contentTypeId 
Quest’ultimo si rifà al metodo descritto in 3., con l’unica eccezione che il il template della lista è predefinito in SPTemplateListType.GenericList. 
3 http://msdn.microsoft.com/en-us/library/ff798404.aspx come riferimento e descrizione riguardo il Content type di una lista o document Library
41 
3.3.1.5 Mailer 
La classe mailer è tra le più importanti, se non la più importante tra quelle sviluppate. 
Il metodo di gestione della mail in SharePoint funziona in maniera similare ai classici event handler esistenti: può essere integrata la sua gestione all’interno di un workflow o ad un qualsiasi evento di alert, ma non a degli eventi custom operativi a prescindere. 
Questo è lo scopo del mailer proposto: fornire dei metodi che garantiscano, indipendentemente dalla struttura a workflow o da eventi scatenati dal sistema stesso, la gestione della mail, i relativi contenuti, i mittenti ed i destinatari in modo più autonomo e libero possibile. 
Essendo poi la società orientata a non sfruttare la struttura di workflow proposta, è fondamentale una gestione esterna di tali processi, in modo tale da poter usuffruire ugualmente di un servizio che risulta sempre più importante nella pianificazione, sviluppo e gestione di un ciclo produttivo industriale in maniera completa ed efficiente. 
Dunque, la classe fornirà primariamente 4 diversi metodi, ed un costruttore di classe per definire il tipo EmailTemplate, che descriverà subject e body della mail stessa. 
È inoltre interessante notare che, a differenza di tutte le altre classi, gli import da package esterni è molto più vasto, specie per poter consentire l’uso di server SMTP per l’invio delle mail stesse. 
Gli import eseguiti sono: 
o System.Net4: permette di avere metodi di gestione dei protocolli di comunicazione su reti 
o System.Net.Mail5: è il namespace che permette la gestione dell’invio dei messaggi tramite il server SMTP; 
o System.Collections.Specialized6: namespace che permette una gestione di raccolte particolarmente specializzate o tipizzate 
4 http://msdn.microsoft.com/it-it/library/system.net.aspx 
5 http://msdn.microsoft.com/it-it/library/system.net.mail.aspx ne descrive metodi e funzioni 
6 http://msdn.microsoft.com/it-it/library/system.collections.specialized.aspx
42 
o Microsoft.Sharepoint.Administration7: namespace che permette una più vasta gestione dei tipi e membri da configurare durante il deploy; 
o Microsoft.Sharepoint.Utilities8: comprende un insieme di metodi per una più pratica gestione della piattaforma SharePoint; 
o System.Web.UI.WebControls9: consente la creazione di controlli server all’interno di una pagina web, risultando necessario nel caso di utilizzo del metodo all’interno di ulteriori event handler. 
3.3.1.5.1 Class EmailTemplate 
È strutturata in maniera molto semplice: 
o Una stringa pubblica di Subject; 
o Una stringa pubblica di Body; 
o Un costruttore di classe che setta i due valori definiti in precedenza 
3.3.1.5.2 Void createEmailTemplateList 
Questo metodo è utile a preparare l’ambiente per la gestione delle mail all’interno della site collection, definendo la lista di appoggio in cui vanno inserite i template delle mail da inviare, con i relativi placeholder da rimpiazzare nel momento di personalizzazione della stessa. 
Il metodo ha come argomenti queste variabili: 
o SPWeb web; 
o Dictionary<String, EmailTemplate> emailTemplates: è l’insieme dei templates passati per la generazione della lista di configurazione; 
o KeyValueList.KeyValueListPermissions permissions: sono i permessi per la generazione della lista di configurazione; 
o Boolean forceToElevatedPrivileges 
Ed esegue questa funzione: 
1. Viene creato un nuovo Dictionary<String, String> denominato keys; 
2. Per ogni key dell’emailTemplates, vengono generate due key all’interno di keys con tale struttura: 
7 http://msdn.microsoft.com/it-it/library/microsoft.sharepoint.administration.aspx 
8 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.utilities.aspx 
9 http://msdn.microsoft.com/it-it/library/system.web.ui.webcontrols.aspx
43 
Key 
Value 
Key + “body” 
emailTemplates[key].body 
Key + “Subject” 
emailTemplates[key].subject 
3. Viene invocato il metodo KeyValueList.CreateKeyValueList(web, EMAIL_TEMPLATE_LIST, keys, permissions, forceToElevatedPrivileges), per ottenere la lista di nostro interesse. 
La necessità di spezzare in due keys si basa sul fatto di poter usufruire dei metodi generati in precedenza, cosicché non si debba creare ulteriore codice già fornito da funzioni similari già scritte. 
3.3.1.5.3 Void getEmail 
Questo è il metodo che va a pescare dalla lista generata in precedenza fornendo body e subject della mail da inviare, e sostituendo i placeholder con i valori reali da introdurre. 
Gli argomenti in ingresso sono: 
o SPWeb web; 
o String emailType: definisce il tipo di emailTemplate da pescare; 
o Dictionary<String, String> replaceTable: è la lista con cui vengono sostituiti i placeholder con i valori reali; 
o Out String body: è il valore del body che viene restituito in uscita; 
o Out String subject: è il valore del subject restituito in uscita 
È importante sottolineare un fatto: il replaceTable è un dictionary che, pur avendo una struttura implementabile a livello generico, si è scelto di consentire allo sviluppatore di averne piena libertà di creazione, lasciando questa senza un metodo di composizione appropriato. Poiché ogni implementazione del servizio mail è costumizzato in maniera specifica al progetto di interesse, vincolare la raccolta dei dati renderebbe praticamente bloccata la struttura di tutta la site collection, bloccando liste, dati, contenuti e particolarità che il cliente potrebbe andare a richiedere per la propria applicazione. 
Da un’analisi teorica, il dictionary andrebbe ricreato ogni volta, poiché sono sin troppe le variabili in gioco che potrebbero cambiare (numero di placeholder, ente invocante, ente
44 
ricevente, variabili da inserire nei placeholder, per citarne alcuni), che non permettono di avere un oggetto (item di una lista) fisso da sfruttare. 
Nel caso di una lista, ipotizzando di avere n campi con m possibili valori teorici per ognuno di essi, avremmo un ordine di grandezza di nm, generando una mole di dati ingestibile all’aumentare di n ed m, oltretutto portando ad un vantaggio in termini di tempo a dir poco irrisorio: l’accesso alle liste è praticamente immediato, ed allo stesso modo recuperare i valori all’interno degli items selezionati. Una minima perdita in termini di tempo sopperisce appieno al risparmio in termini di spazio occupato che proporrebbe l’altro tipo di soluzione. 
Tornando a parlare del metodo, esso esegue queste operazioni: 
i. Nelle variabili body e subject in ingresso vengono posti dei valori di esempio; 
ii. Vengono recuperati, tramite il metodo della classe KeyValueList GetKeyValue i contenuti di body e subject di interesse per la mail; 
iii. Per ogni keyValuePair presente nel dictionary, viene verificata la possibile sostituzione del placeholder: se il value non è null, viene presa la sezione del placeholder (caratterizzata da “%”+ entry.key + “%”) e sostituita sia nel body che nel subject dal value effettivo, oppure, nel caso contrario, con uno spazio vuoto; 
Tutto il processo è interno ad un try / catch, che in caso di errore generico manda una segnalazione nel log di sistema. 
3.3.1.5.4 Void Send 
Questo metodo consente l’effettiva generazione della mail e il conseguente invio della stessa tramite il metodo fornito dalle SPUtility SendEmail, senza avere degli allegati ad essa associata (per gli allegati, si rimanda al metodo successivo). 
Come signature, il metodo ha: 
o SPWeb web; 
o String to: è l’indirizzo mail del destinatario; 
o String tipoMail: è il tipo di mail template da recupare; 
o Dictionary<String, String> replaceTable; 
o String from: è l’indirizzo mail del mittente; 
o String emailCC: sono gli indirizzo mail degli utenti a cui la mail viene inoltrata in copia.
45 
Il flusso è così descritto: 
Figura 18 - Flusso Send 
Come è possibile constatare, il metodo verifica la presenza dei campi nulli per i ruoli cardine dell’invio della mail (mittente), generando un’exception nel caso di valori mancanti. 
A completare, associato a questo stesso metodo ve ne è un altro in overload, con signature leggermente diversa: 
o Invece di avere una variabile to di tipo string, ne abbiamo una identica di tipo SPUser 
String messaggio; 
String oggetto 
getEmail(web, tipoMail, replaceTable, out oggetto, out messaggio) 
stringDictionary headers = new StringDictionary() 
headers.Add(“to”, to); 
From != null 
Errore 
Headers.Add(“from”, from) 
emailCC != null 
Headers.Add(“cc”, emailCC) FALSO FALSO VERO VERO 
Headers.Add(“subject”, soggetto) 
Headers.Add(“content-type”, “text/html”) 
SPUtility.SendEmail(web, headers, messaggio)
46 
FALSO 
Urls != null 
Foreach(url) 
Tr 
y 
SPFile file = web.GetFile(url) 
Message.Attachments.Add(new 
Attachment(file.OpenBinaryStream(), file.Name) 
Errore 
VERO 
FALSO 
VERO 
EXCEPTION E 
Questo dunque andrà a recuperare la mail associata allo User passato e, se questa risulterà 
esistere, verrà inviata la mail invocando il metodo descritto sopra. 
3.3.1.5.5 Void SendWithAttachments 
Quest’ultimo metodo della classe è decisamente più articolato dei precedenti, poiché 
l’implementazione dell’inserimento degli allegati richiede numerosi passaggi supplementari. 
Oltre agli argomenti descritti nel metodo Send, quest’ultimo ha una variabile supplementare: 
o String[] urls: il percorso dei file da allegare 
Il metodo, dopo aver definito le string messaggio e oggetto, crea un nuovo oggetto di tipo 
MailMessage, a cui vengono associati, se presenti, mittenti, destinatari e lettori in copia (con le 
stesse restrizioni presenti in Send). 
Dopo aver associato alle properties dell’oggetto MailMessagge i valori 
Property Value 
isBodyHtml True 
Body messaggio 
Subject oggetto 
Viene verificata la presenza di elementi nell’array urls 
Figura 19 - Flusso SendWithAttachments
47 
In modo tale da consentire l’associazione al messaggio di tutti gli allegati effettivamente esistenti, senza generare problemi verso quelli funzionanti ed associabili. 
A questo punto, poiché non è possibile utilizzare il metodo SPUtility.SendEmail proposto in Send, dato che questo non gestisce propriamente gli allegati, c’è il bisogno di ricreare l’ambiente smtp per l’invio della mail: 
o Viene recuperato il Local.OutboundMailServiceInstance, che è l’istanza locale che definisce i settaggi per l’invio delle mail tramite smtp; 
o Se non esistente il serviceInstance descritto al punto precedente, viene settato come suo valore il web.Site.WebApplication.OutboundMailServiceInstance, così da avere quello stesso della site collection; in caso di assenza pure di questo si da errore e viene impedito l’invio; 
o A questo punto viene recuperato l’smtp server address tramite il serviceInstance.Server.Address, e generato un nuovo smtp client puntato a questo indirizzo; 
o Ora non resta che inviare il message tramite il comando client.Send(message) 
La necessità del controllo sul Local.OutboundMailServiceInstance è per ovviare al valore null che questo assume arbitrariamente, impedendo l’invio stesso della mail al metodo. Con il web.Site.WebApplication.OutboundMailServiceInstance i rischi di null exception si riducono al minimo, garantendo dunque il corretto funzionamento dell’smtp client.
48 
3.3.1.6 PubManager 
La classe PubManager fornisce quei metodi che permettono la configurazione delle PublishingWeb10 e PublishingPage11 classes. 
PublishingWeb, come descritto nelle specifiche Microsoft, “provides publishing-specific behavior for an SPWeb that supports publishing, including access to child PublishingPage and PublishingWeb instances, variations support, navigation settings, PageLayout and Web template restrictions, and Welcome page settings. This class wraps an SPWeb instance that has the publishing feature activated”. In questo modo, nelle site collection in cui vi è implementata la feature di publishing al suo interno, viene permessa la definizione custom di tutte quelle pagine su cui potranno intervenire gli utenti finali tramite il front-end della site collection, configurando primariamente i permessi su PageLayout e sul Web Template, e gestendo gli accessi sulle Pagine di Publishing e sui Web di Publishing figlie di questa. 
PublishingPage invece, sempre dalla specifiche Microsoft, “contains references to the parts that define the .aspx page, such as the PageLayout class, the SPContentType class, resources, and other parts. It contains PublishingPage content as field values in the document library item”. In questo modo le possibili pagine di Publishing, oltre che ad ereditare dal PublishingWeb, può aver definite le proprie caratteristiche particolari usando le strutture base di SharePoint (in questo caso, Document Library) e venendo trattata come un qualsiasi altro item, e dunque con le stesse personalizzazioni. 
Anche in questo caso vi è la necessità di creare un oggetto che definisca un insieme di variabili, che verrà definito PageDefinition. Invece di creare una classe pubblica, si è optati di usare uno struct, visto che non abbiamo metodi costruttori ma unicamente variabili al suo interno. I metodi ritenuti utili alla causa invece sono sette, con, in alcuni casi, overload di questi. 
3.3.1.6.1 Struct PageDefinition 
Lo struct ha 7 variabili private al suo interno, a cui vi si ha accesso tramite i metodi get / set ad esse associati: 
 String pageFileName: è l’url della PublishingPage da generare; 
 String pageTitle: è il titolo della PublishingPage; 
10 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.publishingweb.aspx 
11 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.publishingpage.aspx
49 
 String controlPath: è l’url, se definito, dello user control associato alla pagina; 
 String pageLayout: è il nome della PageLayout associata alla PublishingPage; 
 Boolean includeInCurrentNavigation: indica se inserire o no nel site (o subsite) di pertinenza il suo link diretto; 
 Boolean includeInGlobalNavigation: indica se inserire o no nella site collection di pertinenza il suo link diretto; 
 String webPartZoneId: legato al controlPath, definisce in quale WebPartZone inserire lo user control definito in precedenza. 
3.3.1.6.2 PublishingPage CreatePublishingPage 
Il primo metodo implementato è quello che operativamente crea la PublishingPage e lo inserisce all’interno della PublishingPageCollection passato in ref. 
Come argomenti abbiamo: 
o SPWeb web; 
o String pageNameUrl: è l’url della pagina da generare; 
o String pageTitle: è il titolo della pagina; 
o String pageLayoutName: è il nome del PageLayout da associare; 
o Ref PublishingWeb pubWeb: è la PublishingWeb da cui pescare, in caso di evenienza, la PublishingPageCollection; 
o Ref PublishingPageCollection pubPages: è l’insieme delle pagine a cui verrà aggiunta quella in fase di creazione. 
Il funzionamento è il seguente: 
i. Se pubWeb è vuoto, vengono associate ad esso le PublishingWeb di web tramite il metodo PublishingWeb.GetPublishingWeb(web); 
ii. Se pubPages è vuota, viene associata la collection di PublishingPages di pubWeb tramite il metodo pubWeb.GetPublishingPages(); 
iii. Viene creato un oggetto PageLayout recuperando dal web quello definito con il name pageLayoutName con il metodo GetPageLayout(web, pageLayoutName) (che verrà descritto a breve);
50 
iv. Viene creato un riferimento PublishingPage chiamato pubPage a cui viene associato l’oggetto che viene creato all’interno di pubPages con il metodo pubPages.Add(pageNameUrl, pageLayout); 
v. Viene valorizzata la property Title di pubPage con il valore pageTitle, ed eseguito un update dell’oggetto stesso. 
Il valore restituito sarà la stessa PublishingPage generata. 
In caso di eccezioni, verrà generato un messaggio di Log con i riferimenti a ciò che a portato questo errore. 
Il metodo, oltretutto, effettua un overload in cui la signature manca degli argomenti webPub e webPages: il metodo setterà questi a null e invocherà il metodo appena descritto. 
3.3.1.6.3 PageLayout GetPageLayout 
Questo metodo accessorio è utile nel CreatePublishingPage per recuperare il PageLayout associato alla stringa passata. Gli argomenti del metodo sono: 
o SPWeb web; 
o String pageLayoutName; 
Il metodo recupera il PublishingSite della site Collection, e l’associata PageLayoutCollection, va a prendere il relativeUrl in questione. 
Se la stringa ottenuta risulta uguale al solo “/”, stando ad indicare che ci si trova di fronte ad una site collection posta come primaria all’interno della Web Application, andremo ad attingere direttamente da “/_Catalogs/masterpages/<PageLayoutName>”; viceversa, nel caso ci trovassimo in una site collection più interna, avremmo come indirizzo di riferimento “<web.Site.RelativeUrl>/_catalogs/masterpages/<PageLayoutName>”. 
3.3.1.6.4 List<PageDefinition> CreatePageDefinitionList 
Questo metodo di appoggio permette di creare, come definito dalla signature, la lista delle PageDefinition da dare in pasto alle altre funzioni prendendo i dati dalla matrice passata in input. 
Unica variabile di input è la matrice di String[,] pageDefinitionMatrix, che conterrà i valori, in ordine:
51 
 PageFileName; 
 PageTitle; 
 ControlPath; 
 PageLayout; 
 WebZonePartId; 
 IncludeInCurrentNavigation; 
 IncludeInGlobalNavigation; 
Per poter popolare l’oggetto PageDefinition in creazione. 
Il metodo analizzerà tale matrice, e per ogni riga, fino al raggiungimento dell’UpperBound, verrà generato un oggetto PageDefinition con i valori relativi, ed inserito all’interno di una lista, che sarà oltretutto l’output della funzione stessa. 
3.3.1.6.5 List<PublishingPage> CreatePublishingPagesSetWelcome 
Questo metodo porta alla generazione della Lista delle publishing Pages. Come argomenti della signature abbiamo: 
o SPWeb web; 
o List<PageDefinition> pageDefinitions: è la lista con le PageDefinition da convertire in publishing Pages; 
o String welcomePageFileName: è il nome della pagina che diventerà quella di Welcome. 
La costruzione della lista di PublishingPages avviene sin dall’inizio, e viene seguita dalla configurazione della SPFile welcomePage, della PublishingWeb pubWeb e della PublishingPageCollection pubPages a null. 
Dunque, per ogni PageDefinition all’interno della lista, viene avviato un try / catch strutturato che permetterà di poter creare tutte le Publishing pages effettivamente funzionanti, senza dare un blocco nel caso di malfunzionamento di una di queste. 
Completato, si passa alla fase di associazione della welcomePage: nel caso il valore della stringa risultasse non nulla: 
i. Si rompe la navigazione sia per la CurrentIncludesPages che per la GlobalIncludePages; 
ii. Viene settata la pagina definita come pubWeb.DefaultPage;
52 
iii. Viene eseguito un update del pubWeb; 
iv. Viene chiuso pubWeb 
Da evidenziare, oltretutto, che il metodo stesso ha un caso di overload così definito: 
o Invece della List<PageDefinition>, viene passata una matrice pageDefinitionMatrix: verrà invocato nuovamente il metodo, con List<PageDefinition> ricavata tramite il metodo CreatePageDefinitionList(pageDefinitionMatrix). 
Figura 20 - Flusso CreatePublishingPagesSetWelcome 
VERO FALSO VERO FALSO Try publishingPage pubPage = PubManager.CreatePublishingPage(…) pubPage.IncludeInCurrentNavigation pubPage.IncludeInGlobalNavigation pageFileName == welcomePageFileName welcomePage = pubPage.ListItem.File pubPage.checkOut() pageDefinition.ControlPath != null Inserimento WebPart pubPage.checkIn() pubPage.ListItem.File.Approve(String.Empty) pubPage.ListItem.File.Publish(String.Empty) pages.Add(pubPage) Log Error EXCEPTION E
53 
3.3.1.6.6 List<PublishingPage> CreatePublishingPages 
Il metodo proposto è una semplice modifica del metodo descritto al punto precedente: oltre la matrice ed all’SPWeb, non verrà passato altra variabile. Il return invocherà il metodo CreatePublishingPagesSetWelcome(web, CreatePageDefinitionList(pageDefinitionMatrix), String.Empty). 
In tale modo non verrà configurata la pagina di Welcome, e verranno conservate le definizioni di pubWeb.CurrentIncludePages e pubWeb.GlobalIncludePages. 
3.3.1.6.7 Void DeletePublishingPagesSetWelcome 
Al contrario dei precedenti, questo metodo va a rimuovere le Publishing Pages presenti all’interno della lista di PageDefinition in input, e va nuovamente a configurare la Welcome Page. 
I parametri di input sono similari ai precedenti metodi: 
o SPWeb web; 
o List<PageDefinition> pageDefinitions; 
o String welcomePageFileName. 
In questa circostanza, viene: 
i. Recuperato il pubWeb da web; 
ii. Recuperato il pubPages da pubWeb; 
iii. Creato il percorso per associare la nuova WelcomePage, nel caso in cui welcomePageFileName non fosse nulla; 
iv. Per ogni pegeDefinition in pageDefinitions, viene rimosso l’item presente in pubPages associato al pageFileName tramite un try / catch; 
v. Chiuso il pubWeb. 
Da notare il “barbaro” utilizzo del try / catch al punto iv. Il catch vuoto, contrario ad ogni tipo di programmazione pulita e funzionale, è dovuto al fatto che SharePoint, nella versione 2007, non ha avuto un metodo che eseguisse il tentativo di ricerca dell’oggetto, senza andare in errore se questo non fosse esistente. In tal maniera, oltre ad avere un controllo sull’effettiva
54 
esistenza dell’oggetto, permettiamo anche una retrocompatibilità del metodo con la versione 2007 della piattaforma. 
A chiudere la trattazione su questo metodo, è bene far notare, in maniera similare al caso di CreatePublishingPagesSetWelcome, esiste un metodo in overload per questo stesso, con variabili di ingresso variate (invece che List<PageDefinition> la matrice pageDefinitionMatrix), ma stesso comportamento, con return invocante il metodo. 
3.3.1.6.8 Void DeletePublishingPages 
In maniera similare al CreatePublishingPages, riceve come input la matrice PageDefinitionMatrix, setta come String.Empty la WelcomePage e richiama il metodo DeletePublishinPagesSetWelcome con argomenti web, pageDefinitionMatrix, String.Empty.
55 
3.3.2 Classi accessorie 
All’interno della feature descritta, sono state anche introdotte delle classi di supporto che si sono rese necessarie per un corretto e completo funzionamento di quelle descritte precedentemente. 
Due sono i blocchi cruciali da analizzare: i metodi forniti per il logging e quelli per la gestione delle security di SharePoint. 
3.3.2.1.1 Logging 
La sezione di logging riveste un ruolo molto importante, in modo particolare nelle situazione di errore del prodotto: quest’ultima ci permette difatti di verificare, tramite un report puntuale, cos’è che ha causato l’eccezione. 
Potrebbe sembrare una funzione poco funzionale alle specifiche proposte, ma è utile, se non fondamentale, per lo sviluppatore in caso di problemi riscontrati durante il funzionamento della solution. 
È importante sottolineare, se non troppo evidenziato prima, che praticamente ogni metodo di quelli descritti nelle classi in precedenza usufruiscono di quelli descritti in questa sezione, proprio per i motivi citati sopra. 
Questa parte di feature è stata spezzata in due classi: quella di Logger, con la creazione della lista di log, i relativi costruttori e i metodi associati, e la LogExceptions, con i metodi che invocano i precedenti per una commistione corretta a seconda degli stati in cui ci si trova. 
L’elenco di metodi e classi, ora, sarà unificato, elencando prima quelli di Logger.cs, dunque quelli di LogExceptions.cs. 
3.3.2.1.1.1 Class Logger 
La classe ha 4 variabili private: 
 SPWeb web; 
 SPListItem spFeatureLogItem; 
 SPFile spLogFile; 
 String logName.
56 
Sono tutte a null in origine, e poi verranno popolati, a seconda del caso, tramite i costruttori di classe: 
1. Logger (SPWeb destinationWeb, string feature) 
In questa prima situazione viene invocato unicamente il metodo Inizialize con i due input come suoi argomenti di ingresso (Inizialize verrà descritto a breve) 
2. Logger (SPWeb destinationWeb, String feature, String logName) 
Questo secondo costruttore, invece, setta la variabile privata logName con il parametro di ingresso, per poi operare come quello precedente. 
Comprende inoltre un insieme di metodi atti a creare la lista di log, scrivervi al suo interno e gestirne gli item al suo interno. 
3.3.2.1.1.1.1 SPList CreateLogListIfNotExists 
È il metodo di creazione della lista di log nella site collection SharePoint di nostro interesse. È un metodo privato. 
Senza argomenti in ingresso, pesca dalla variabili globali l’SPWeb, e si collega alla Lista di log. Se questa non venisse trovata, viene creata una nuova GUID riferita alla nuova lista generata, e modificata la colonna “title” chiamandola con la costante TITLE_LOG_LIST. 
Tutta il metodo sarà poggiato su due try/catch intrecciati tra loro: nel caso di malfunzionamento di entrambe le sezioni, verrà ritornato un valore null. 
3.3.2.1.1.1.2 Void OpenLog 
È il metodo, privato, che verifica l’esistenza di un item nella lista di log e, se non esistente, crea un nuovo item, predisponendolo ad una successiva compilazione. 
Ha come argomenti in ingresso: 
 String feature: è il nome da attribuire al log item; 
 SPList spLogList: è la lista di log 
Il metodo opera secondo questo diagramma di flusso semplificato:
57 
Figura 21 - Flusso OpenLog 
Il tutto viene eseguito con metodi già forniti dalle libraries a disposizione, tranne il metodo AddAttachmentToSPItem(), appartenente a questa stessa classe, che definiremo in seguito. 
3.3.2.1.1.1.3 Void AddAttachmentToSPItem 
A completamento del metodo precedente, questo va ad associare gli attachments dell’item in maniera corretta, ripulendoli e portandoli ad un valore inferiore del MAX_LENGTH definito all’interno della classe. Anch’esso è privato e non ha variabili di input. 
Opera nella maniera seguente: 
 Setta a true gli UnsafeUpdates; 
Exists = false 
Controllati tutti gli item 
Esiste 
Exists = true 
spFeatureLog = listItem 
Exists 
Crea spFeatureLog 
logName != null 
url dei possibili attachments 
Attachments 
logFile.length > MAX_LENGTH 
spLogItem.Attachments.DeleteNow(logName) 
AddAttachmentToItem() VERO VERO VERO VERO FALSO FALSO FALSO FALSO FALSO VERO
58 
 Recupera la Collection di Attachments associata all’item; 
 Verifica la presenza del logName: in caso affermativo crea una stringa defLogName con quel valore 
 In caso contrario, definisce defLogName con valore la data formattata; 
 Viene aggiunto un Attachment con i parametri di pertinenza; 
 Viene recuperato l’SPFile associato al log e settato come spLogFile; 
 Setta a false gli UnsafeUpdates 
3.3.2.1.1.1.4 Void Initialize 
È il metodo invocato dal costruttore, creando l’ambiente adatto alla verifica ed alla generazione della log list all’interno della site collection selezionata. 
Ha due argomenti in input: 
 SPWeb web; 
 String feature. 
Ed opera in maniera molto semplice: 
1. Viene recuperata la stringa dell’url del web passato; 
2. Vi si accede in modalità elevated privileges, creando un nuovo site; 
3. Vengono settati all’interno di quest’ultima i permessi per gli UnsafeUpdates; 
4. Viene invocato il metodo CreateIfNotExists() 
5. Viene dunque verificata l’effettiva presenza (o creazione) della lista: in caso affermativo, viene avviato OpenLog(feature, spLogList), così da essere predisposti alla compilazione di un item; 
6. Viene dunque revocato il permesso agli UnsafeUpdates 
L’utente sarà così abilitato alla compilazione dell’item di pertinenza per quella exception o informazione che risulterà necessaria in fasi successive di analisi prestazionali. 
3.3.2.1.1.1.5 String LogLine 
È un metodo privato, che ritorna il contenuto da passare agli item nel campo di descrizione. Suddivide in tre possibili tipi di notifiche: ERROR, WARNING, INFO, definendo una variabile pubblica enum nella classe stessa.
59 
La stringa di ritorno sarà così strutturata: <DateTimeAttuale> + <TipoNotifica> + <Messaggio Personalizzato>. 
3.3.2.1.1.1.6 Void Write 
È il metodo che va a popolare l’SPFile associato al log. Ha come argomenti di ingresso: 
 LOG_TYPE type: è il tipo di log che verrà generato; 
 String message; 
Dopo aver dato i permessi agli UnsafeUpdates, viene aperto uno stream sull’spLogFile esistente, dunque uno StreamWriter su quest’ultimo. 
Dunque viene identificato il punto in cui iniziare a scrivere (tramite il metodo Seek), e scritta la riga di interesse tramite il LogLine. Dopo aver ripulito sia lo StreamWriter che lo Stream tramite il relativo metodo flush (svuotando il buffer associato a questi), e salvando il BinaryStream nell’SPFile, viene completata l’operazione. 
3.3.2.1.1.1.7 Int AttachmentsLogComparator 
È un metodo accessorio utile per il clearAttacchments (che descriveremo subito dopo), in cui viene eseguita la comparazione temporale tra due SPFile, e la loro data di ultima modifica. 
Presi A e B due SPFile, verrà ritornato: 
 -1 se A.TimeLastModified < B.TimeLastModified; 
 0 se A.TimeLastModified = B.TimeLastModified 
 1 altrimenti 
3.3.2.1.1.1.8 Void ClearAttachments 
Questo metodo verifica e rimuove gli attachments in eccesso, rimuovendo quelli che risulteranno i più vecchi. 
Il metodo ha una unica variabile di ingresso: l’int maxNumAttachments, che determina, come dice il nome stesso, il numero massimo di di Attacchments associati al log. 
Recuperati gli attachments associati all’item di interesse, verifichiamo se il numero di questi superino il numero massimo imposto di attachments. Se superiore, vengono recuperati tutti gli item, riferiti all’interno di una Lista di appoggio spFileList.
60 
Su spFileList viene eseguito un sorting che ha come metodo di comparazione l’attchmentsLogComparator definito poco sopra, e, completato questo, vengono eliminati quelli che sono i valori più vecchi nella lista, invocando il delete(). 
Importante sottolineare che il metodo Delete() non rimuove il riferimento nella lista, ma propriamente l’SPFile associato, in modo tale da rimuoverlo pure all’interno degli Attachments dell’spFeatureLogItem. 
3.3.2.1.1.1.9 void Close 
Senza argomenti nella signature, fa il Dispose del web utilizzato, rilasciando tutte le risorse non utilizzate. 
3.3.2.1.1.2 Class LogExceptions 
Questa seconda classe della sezione poggia direttamente su Logger, invocandone sistematicamente metodi e costruttori per poter gestire in maniera ordinata e vincolata tutte le funzioni garantite. 
Esistono due metodi fondamentali, il LogMessage ed il ManageException, che strutturano, in maniera differente, il logger a disposizione, supportati da alcuni metodi accessori. 
3.3.2.1.1.2.1 Void Alert 
Metodo di generazione di alert, che vada a visualizzare un messaggio predefinito, sotto forma di popup, nella pagina in cui si è verificato l’errore. 
3.3.2.1.1.2.2 Void LogMessage 
In questo metodo viene generato un nuovo Attachment legato al log. 
Come parametri di ingresso abbiamo: 
 SPWeb web; 
 String message: il messaggio da salvare; 
 String featureName: è il nome della feature che ha generato il log; 
 Int maxAttachments: il numero massimo di attachments che può avere il log associato; 
 Logger.LOG_TYPE level: è il tipo di log da generare 
Il metodo si limita ad invocarne altri: 
1. Inizialmente invoca il costruttore di Logger, con i parametri necessari
61 
2. Creato l’oggetto log, ne invoca i metodi Write, ClearAttachments e Close in sequenza 
Effettua anche l’overload, senza la variabile LOG_TYPE: in questo modo, viene pre-impostato che il log si di error. 
3.3.2.1.1.2.3 Void ManageException 
Strutturato in maniera similare al LogMessage, si differenza del precedente inserisce due righe di log all’interno dell’attachment, una che descrive classe e funzione che hanno generatore l’eccezione, e la seconda l’eccezione stessa. 
Come parametri aggiuntivi, rispetto a LogMessage, difatti ha due stringhe className e functionName, inserite direttamente dal metodo invocante per descriverne l’origine. 
3.3.2.1.1.2.4 Void ManageExceptionGenericAlert 
Quest’ultimo metodo di classe invoca i precedenti ManageException e Alert, per fornire sia un messaggio nel log che un pop up in uscita. 
3.3.2.1.2 Security 
La sezione di Security permette una gestione maggiormente efficace dei permessi forniti per l’utente all’interno della piattaforma SharePoint, fornendo dei metodi di assegnazione e di rimozione di tali nella site collection. 
Le security all’interno di SharePoint hanno una profonda importanza per tutta l’ambiente, poiché sono definibili ed impostabili a qualsiasi livello, dalla web application, scendendo per la site collection, le pages, le liste e le document Libraries, fino ad arrivare al singolo item, consentendo un accesso e diritti di creazione, editing, rimozione e visualizzazione in ogni più minimo particolare. 
Introducendo brevemente le funzionalità dei permessi, come già visto nella creazione di gruppi utenti, questi possono essere attribuiti a singoli utenti (pescati dall’Active Directory se attivata unicamente la Windows Authentication, oppure tramite oAuth o una claim-based authentication, oppure ancora direttamente da un database di credenziali personalizzato), a zero o più gruppi (popolati con le utenze), ed essere di tipo diverso, a seconda delle autorizzazioni che si vogliono concedere.
62 
L’ambiente12 propone di default cinque livelli per i team sites (quelli che sono solitamente i template più utilizzati in ambito aziendale per la produzione di site collections) e innumerevoli permessi specifici da poter configurare. 
Per essere chiari, nella prossima parte della trattazione definiremo Securable tutti quegli elementi di SharePoint cui è possibile applicare dei criteri di visibilità puntuale, che essi siano item, list, document library, e via dicendo. 
Dunque, nel caso dei livelli, si passa da: 
 Limited Access, in cui l’utente / gruppo ha unicamente diritto di accesso alle risorse condivise (è un particolare livello, perché si tende ad utilizzarlo per sgranarne meglio i permessi della stessa utenza in casi più specifici, definendo caso per caso, Securable per Securable, il tipo di autorizzazione concessa); 
 Read, in cui l’utenza può leggere i contenuti del Securable autorizzato; 
 Contribute, in cui è possibile, oltre alle autorizzazioni precedenti, creare items all’interno di Lists e Document Library 
 Design, in cui l’utenza, assieme ai permessi del Contribute, può modificare le pages e approvare gli items generati da altre utenze; 
 Full Control, in cui l’utente / gruppo può compiere qualsiasi operazione sul Securable preso in considerazione. 
Questi livelli permettono di avere una sgranatura abbastanza ampia degli user all’interno della web application presa in considerazione, ma nel caso avessimo bisogno di una più approfondita suddivisione dei ruoli, vi è la possibilità di configurare, uno ad uno, tutti i permessi concessi e distinti, personalizzati per ogni tipo di Securable disponibile. 
Altro tema toccato all’interno di questa sezione, è la protezione di contenuti sensibili privati, come ad esempio password all’interno di liste di configurazione. Non è sufficiente togliere i permessi di view sull’item stesso, perché nel caso di utilizzo di questa per determinate funzionalità, non risulterebbe utilizzabile. Dunque si può preferire l’inserimento di un sistema di codifica e decodifica di questi contenuti, con due metodi ad hoc. 
12 http://technet.microsoft.com/it-it/library/cc721640(v=office.14).aspx per maggiori approfondimenti sul tema dei permessi in ambiente Sharepoint 2010
63 
Andiamo ora in descrizione delle due classi sviluppate, una chiamata Permissions, l’altra EncodeDecode, in modo da vederne le funzionalità implementate. 
3.3.2.1.2.1 Class Permissions 
Vi sono 4 metodi (in overload) per la gestione degli Assignments, mentre 2 per la rimozione di tutti i permessi. 
3.3.2.1.2.1.1 Bool Assign 
Metodo che permette l’assegnazione dei permessi rispetto un item od una lista rispetto ad una determinata utenza, o gruppo. Restiuisce true nel caso siano assegnati i permessi direttamente al Securable indicato, false in caso contrario. 
Ha 4 overload, con unico argomento comune l’SPPrincipal, che è la property che users, groups e ad Users hanno condivisa, mentre si differenziano per il tipo di Securable da autorizzare (SPList o SPListItem), e dalla modalità in cui viene definito il permesso (SPRoleType o SPRoleTypeDefinition). 
Al posto di Securable può essere inserito a scelta un item o una list (la stessa document library può essere trattata, in questa situazione, come tale), cosicché tutti gli overload siano descritti in maniera completa. 
La struttura generica del metodo è così descrivibile:
64 
Figura 22 - Flusso Assign 
3.3.2.1.2.1.2 Void DeleteAll 
In maniera similare al precedente, vi sono 2 metodi in overload, uno per gli items, uno per le liste, che vanno a dissociare i permessi già impostati. 
Avendo come parametro di ingresso, a seconda del caso, SPList oppure SPListItem, invoca il metodo BreakRoleInheritance(false), che va a eliminare l’ereditarietà dal padre del Securable e, tramite il boolean false, rimuove pure quelli che erano fino a prima i permessi associati. 
3.3.2.1.2.2 Class EncodeDecode 
Questa seconda classe di security, come già descritto in precedenza, agisce sull’encoding e decoding di stringhe, fornendo rispettivamente un metodo per i due casi. 
SPRoleAssignment = new SPRoleAssignment(spPrincipal) 
SPRoleType 
SPRoleDefinition = […].RoleDefinition.GetByType(spRoleType) 
SPRoleAssignment.RoleDefinitionBindings.Add(SProleDef) 
Permessi specifici per il Securable 
Securable.RoleAssigments.Add(SpRoleAssignment) 
Return true 
Return false 
VERO 
VERO 
FALSO 
FALSO
65 
La classe importa il namespace System.Security.Criptography13, che permette propriamente la gestione di codifica e decodifica dei dati in maniera protetta all’interno della site collection associata. 
I metodi indicati si rifanno all’algoritmo di Rijndael, che è la specifica di implementazione dell’AES, Advanced Encryption Standard, usato come algoritmo standard dal governo degli Stati Uniti, e di cui faremo un approfondimento in appendice. 
Costante privata nella classe, e di rilevante importanza, è IV, stringa di inizializzazione del vettore di codifica dell’algoritmo. 
3.3.2.1.2.2.1 String Encode 
Il metodo di encoding, poiché basato su di un metodo di cifratura a blocchi, necessita della definizione della dimensione del blocco da utilizzare durante la crittografia, e della dimensione della chiave da usare. Per essere aderente allo standard AES, vengono imposte entrambe le dimensioni a 128 bit. 
Parametri di ingresso sono: 
 String S: è la stringa da convertire; 
 String key: è la chiave da usare per la crittazione. 
Il tutto si basa sulla creazione di un oggetto RijndaelManaged chiamato rjm, in cui vengono definiti le properties: 
Property 
Value 
KeySize 
128 
BlockSize 
128 
Key 
ASCIIDecoding.ASCII.GetBytes(key) 
IV 
ASCIIDecoding.ASCII.GetBytes(IV) 
Dunque viene generata lo stream di input, convertendo in formato UTF-8 la stringa in ingresso, salvandola dunque all’interno di un byte[]. 
Ora avviene l’encoding vero e proprio: rjm invoca il createEncryptor, e passa lo stream di input per convertirlo in un nuovo array di byte di output. 
13 http://msdn.microsoft.com/it-it/library/system.security.cryptography(v=vs.80).aspx
66 
A chiusura, l’output viene convertito dall’array in una stringa Base64, così da avere il return di interesse. 
3.3.2.1.2.2.2 String Decode 
In maniera similare a ciò che è stato definito in precedenza, questo metodo esegue il decoding di una stringa generata da Encode. 
Ha le stesse variabili di ingresso, necessita di un RijndaelManaged con uguali properties, variano solo le attività da svolgere sulla stringa di input: 
 Converte la stringa da Base64 in un array di byte; 
 Rjm invoca il metodo di Decoding, restituendo un nuovo array di byte; 
 Quest’ultimo viene convertito in una stringa in formato UTF-8, così da avere il valore effettivo dell’encription.
67 
3.4 Feature BlockUsers 
La seconda feature della solution ha importanza per la gestione delle fasi di manutenzione della site collection su cui questa viene attivata. Ci garantisce difatti il blocco degli accessi a tutte le pagine della site collection quando non si risultasse appartenenti al gruppo degli amministratori di tale. 
Al suo interno viene importato il modulo BlockedUsers, che di conseguenza va a pescare l’ascx BlockUsers.ascx a disposizione nella solution. 
È importante analizzare il funzionamento dell’xml di BlockedUser e di BlockUsers.ascx.cs per capire il funzionamento di tale feature. 
3.4.1 BlockedUsers/Elements.xml 
Il codice di questo file è molto ridotto, ma compie il ruolo fondamentale di delega di un controllo alla source di interesse. 
Difatti, tramite 
Setta il controllo di delega degli accessi a tutte le pagine (tramite l’associazione dell’id GlobalNavigation) alla source ascx BlockUsers, che avrà i suoi metodi di controllo per verificare l’utenza che ne richiede l’accesso. 
Utile constatare che tale ascx viene caricato in automatico al deploy della solution nella piattaforma, ma risulterebbe inutilizzabile ed inutile, se non nel caso di associazione come “filtro” per le utenze aventi diritto di modifica nel momento di manutenzione della site collection.
68 
3.4.2 BlockUsers 
La funzione dell’ascx in questione è molto limitato, ma risulta efficace nel caso in cui abbiamo descritto all’inizio della sezione. 
È tutto concentrato all’interno del PageLoad associato: 
Figura 23 - Flusso BlockUsers
69 
4 Implementazione del framework 
Questa terza sezione del documento va a trattare una possibile implementazione del nostro prodotto all’interno di un effettivo sistema informativo. 
Ciò è utile per dimostrare come il framework possa essere posto a base di un progetto generico per fornire supporto allo sviluppatore, sia a livello logico che a livello di programmazione. 
Andremo dunque ad analizzare un prodotto conseguente del framework in modo da mostrare come questo possa essere usato, procedendo con una descrizione dei requisiti e delle specifiche di progetto, per poi approfondirne una porzione del flusso per mostrare i vari frammenti più interessanti. 
Si evidenzia il fatto che questa parte di trattazione prenderà solo poche delle funzioni andatesi ad implementare nel capitolo precedente, poiché non tutti i metodi sono stati utilizzati all’interno dell’esempio in questione. 
4.1 Esempio di progetto 
4.1.1 Scopo 
La struttura dell’ufficio analizzato è “owner” del processo di gestione delle convenzioni. Tale processo è suddiviso in una serie di fasi consecutive ma che prevedono alcuni ricicli interni per approvazione e/o raccolta documentazione aggiuntiva. 
La forte necessità di avere un’applicazione a governo di tale processo è giustificata dalla necessità di mantenere il raccordo ed il coordinamento delle richieste che provengono dall’esterno e sono traversali. Il sistema si deve fare carico di raccogliere tutte le informazioni in ogni fase del processo e di consentire un’agile gestione di queste. Oltre a gestire lo storico del processo nel tempo. 
4.1.2 Ruoli nel sistema 
Nel processo sono coinvolti attori con diversi ruoli. Ogni attore accede all’applicazione per la consultazione dello stato dei processi di propria competenza, ed eventualmente ne legge il dettaglio, esegue operazioni ed inserisce nuova informazioni.
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010
PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010

Contenu connexe

Tendances

La piattaforma josh - Scenario strategico della piattaforma software di it Co...
La piattaforma josh - Scenario strategico della piattaforma software di it Co...La piattaforma josh - Scenario strategico della piattaforma software di it Co...
La piattaforma josh - Scenario strategico della piattaforma software di it Co...it Consult
 
Progetto e implementazione di un processo per l'assemblaggio di documenti htm...
Progetto e implementazione di un processo per l'assemblaggio di documenti htm...Progetto e implementazione di un processo per l'assemblaggio di documenti htm...
Progetto e implementazione di un processo per l'assemblaggio di documenti htm...Nicola Furlan
 
AreaMVC: un'architettura software basata sulla semplicità
AreaMVC: un'architettura software basata sulla semplicitàAreaMVC: un'architettura software basata sulla semplicità
AreaMVC: un'architettura software basata sulla semplicitàGiulio Destri
 
I processi di sviluppo software: la storia
I processi di sviluppo software: la storiaI processi di sviluppo software: la storia
I processi di sviluppo software: la storiaGiulio Destri
 
Studio e implementazione di uno strumento di configurazione e visualizzazione...
Studio e implementazione di uno strumento di configurazione e visualizzazione...Studio e implementazione di uno strumento di configurazione e visualizzazione...
Studio e implementazione di uno strumento di configurazione e visualizzazione...Matteo Miotto
 
Introduzione alla gestione del progetto software
Introduzione alla gestione del progetto softwareIntroduzione alla gestione del progetto software
Introduzione alla gestione del progetto softwareGiulio Destri
 
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Filippo Muscolino
 
Generazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGenerazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGiacomoZorzin
 
Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide SitoDavide Sito
 

Tendances (10)

La piattaforma josh - Scenario strategico della piattaforma software di it Co...
La piattaforma josh - Scenario strategico della piattaforma software di it Co...La piattaforma josh - Scenario strategico della piattaforma software di it Co...
La piattaforma josh - Scenario strategico della piattaforma software di it Co...
 
Progetto e implementazione di un processo per l'assemblaggio di documenti htm...
Progetto e implementazione di un processo per l'assemblaggio di documenti htm...Progetto e implementazione di un processo per l'assemblaggio di documenti htm...
Progetto e implementazione di un processo per l'assemblaggio di documenti htm...
 
AreaMVC: un'architettura software basata sulla semplicità
AreaMVC: un'architettura software basata sulla semplicitàAreaMVC: un'architettura software basata sulla semplicità
AreaMVC: un'architettura software basata sulla semplicità
 
Relazione Agic
Relazione AgicRelazione Agic
Relazione Agic
 
I processi di sviluppo software: la storia
I processi di sviluppo software: la storiaI processi di sviluppo software: la storia
I processi di sviluppo software: la storia
 
Studio e implementazione di uno strumento di configurazione e visualizzazione...
Studio e implementazione di uno strumento di configurazione e visualizzazione...Studio e implementazione di uno strumento di configurazione e visualizzazione...
Studio e implementazione di uno strumento di configurazione e visualizzazione...
 
Introduzione alla gestione del progetto software
Introduzione alla gestione del progetto softwareIntroduzione alla gestione del progetto software
Introduzione alla gestione del progetto software
 
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
 
Generazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGenerazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptx
 
Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide Sito
 

Similaire à PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010

Progettazione e realizzazione di una piattaforma middleware per la gestione a...
Progettazione e realizzazione di una piattaforma middleware per la gestione a...Progettazione e realizzazione di una piattaforma middleware per la gestione a...
Progettazione e realizzazione di una piattaforma middleware per la gestione a...LucaGre
 
Silverlight in Action
Silverlight in ActionSilverlight in Action
Silverlight in ActionDotNetMarche
 
Automazione dei processi con SharePoint e josh
Automazione dei processi con SharePoint e joshAutomazione dei processi con SharePoint e josh
Automazione dei processi con SharePoint e joshit Consult
 
Reingegnerizzazione di un Content Management System verso l'accessibilità sec...
Reingegnerizzazione di un Content Management System verso l'accessibilità sec...Reingegnerizzazione di un Content Management System verso l'accessibilità sec...
Reingegnerizzazione di un Content Management System verso l'accessibilità sec...Francesco Trucchia
 
Regione Labict Presentazione Ictcollab 20080512 V02
Regione Labict Presentazione Ictcollab 20080512 V02Regione Labict Presentazione Ictcollab 20080512 V02
Regione Labict Presentazione Ictcollab 20080512 V02Gian Luca Matteucci
 
ID Technology Extended ECM for SAP by Open Text
ID Technology Extended ECM for SAP by Open TextID Technology Extended ECM for SAP by Open Text
ID Technology Extended ECM for SAP by Open TextID Technology
 
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...DavideFegez
 
Studio e sviluppo di un sito web responsive attraverso Bootstrap
Studio e sviluppo di un sito web responsive attraverso BootstrapStudio e sviluppo di un sito web responsive attraverso Bootstrap
Studio e sviluppo di un sito web responsive attraverso BootstrapDavide Polotto
 
Soluzioni ot per digicamere giugno 2010
Soluzioni ot per digicamere giugno 2010Soluzioni ot per digicamere giugno 2010
Soluzioni ot per digicamere giugno 2010Giuseppe Bottasini
 
SVILUPPO DI UNA APPLICAZIONE PER L’ACQUISIZIONE DI DATI DA SUPPORTO CARTACEO:...
SVILUPPO DI UNA APPLICAZIONE PER L’ACQUISIZIONE DI DATI DA SUPPORTO CARTACEO:...SVILUPPO DI UNA APPLICAZIONE PER L’ACQUISIZIONE DI DATI DA SUPPORTO CARTACEO:...
SVILUPPO DI UNA APPLICAZIONE PER L’ACQUISIZIONE DI DATI DA SUPPORTO CARTACEO:...guest12aaa586
 
Openatrium come backend caprowsky
Openatrium come backend   caprowskyOpenatrium come backend   caprowsky
Openatrium come backend caprowskyAlessandro Capra
 
Progettazione e sviluppo di un software applicativo su un single board computer
Progettazione e sviluppo di un software applicativo su un single board computerProgettazione e sviluppo di un software applicativo su un single board computer
Progettazione e sviluppo di un software applicativo su un single board computerAlessandro Mascherin
 
eZ magazine: soluzione completa per la gestione multicanale della tua rivista
eZ magazine: soluzione completa per la gestione multicanale della tua rivistaeZ magazine: soluzione completa per la gestione multicanale della tua rivista
eZ magazine: soluzione completa per la gestione multicanale della tua rivistaGabriele Francescotto
 
Cv 2014 richard_gennaro_ eur_it
Cv 2014 richard_gennaro_ eur_itCv 2014 richard_gennaro_ eur_it
Cv 2014 richard_gennaro_ eur_itRichard Gennaro
 

Similaire à PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010 (20)

Progettazione e realizzazione di una piattaforma middleware per la gestione a...
Progettazione e realizzazione di una piattaforma middleware per la gestione a...Progettazione e realizzazione di una piattaforma middleware per la gestione a...
Progettazione e realizzazione di una piattaforma middleware per la gestione a...
 
Silverlight in Action
Silverlight in ActionSilverlight in Action
Silverlight in Action
 
Automazione dei processi con SharePoint e josh
Automazione dei processi con SharePoint e joshAutomazione dei processi con SharePoint e josh
Automazione dei processi con SharePoint e josh
 
Reingegnerizzazione di un Content Management System verso l'accessibilità sec...
Reingegnerizzazione di un Content Management System verso l'accessibilità sec...Reingegnerizzazione di un Content Management System verso l'accessibilità sec...
Reingegnerizzazione di un Content Management System verso l'accessibilità sec...
 
PLM@NET
PLM@NETPLM@NET
PLM@NET
 
Regione Labict Presentazione Ictcollab 20080512 V02
Regione Labict Presentazione Ictcollab 20080512 V02Regione Labict Presentazione Ictcollab 20080512 V02
Regione Labict Presentazione Ictcollab 20080512 V02
 
Tesi_Adamou
Tesi_AdamouTesi_Adamou
Tesi_Adamou
 
ID Technology Extended ECM for SAP by Open Text
ID Technology Extended ECM for SAP by Open TextID Technology Extended ECM for SAP by Open Text
ID Technology Extended ECM for SAP by Open Text
 
Smart api
Smart apiSmart api
Smart api
 
Conoscenza e PA
Conoscenza e PAConoscenza e PA
Conoscenza e PA
 
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
 
Studio e sviluppo di un sito web responsive attraverso Bootstrap
Studio e sviluppo di un sito web responsive attraverso BootstrapStudio e sviluppo di un sito web responsive attraverso Bootstrap
Studio e sviluppo di un sito web responsive attraverso Bootstrap
 
Soluzioni ot per digicamere giugno 2010
Soluzioni ot per digicamere giugno 2010Soluzioni ot per digicamere giugno 2010
Soluzioni ot per digicamere giugno 2010
 
SVILUPPO DI UNA APPLICAZIONE PER L’ACQUISIZIONE DI DATI DA SUPPORTO CARTACEO:...
SVILUPPO DI UNA APPLICAZIONE PER L’ACQUISIZIONE DI DATI DA SUPPORTO CARTACEO:...SVILUPPO DI UNA APPLICAZIONE PER L’ACQUISIZIONE DI DATI DA SUPPORTO CARTACEO:...
SVILUPPO DI UNA APPLICAZIONE PER L’ACQUISIZIONE DI DATI DA SUPPORTO CARTACEO:...
 
Openatrium come backend caprowsky
Openatrium come backend   caprowskyOpenatrium come backend   caprowsky
Openatrium come backend caprowsky
 
Progettazione e sviluppo di un software applicativo su un single board computer
Progettazione e sviluppo di un software applicativo su un single board computerProgettazione e sviluppo di un software applicativo su un single board computer
Progettazione e sviluppo di un software applicativo su un single board computer
 
eZ magazine: soluzione completa per la gestione multicanale della tua rivista
eZ magazine: soluzione completa per la gestione multicanale della tua rivistaeZ magazine: soluzione completa per la gestione multicanale della tua rivista
eZ magazine: soluzione completa per la gestione multicanale della tua rivista
 
Html5 based
Html5 basedHtml5 based
Html5 based
 
Grasso Frameworks Ajax
Grasso Frameworks AjaxGrasso Frameworks Ajax
Grasso Frameworks Ajax
 
Cv 2014 richard_gennaro_ eur_it
Cv 2014 richard_gennaro_ eur_itCv 2014 richard_gennaro_ eur_it
Cv 2014 richard_gennaro_ eur_it
 

PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010

  • 1. UNIVERSITÀ DEGLI STUDI DI TRIESTE PROGETTAZIONE E SVILUPPO DI UN FRAMEWORK DI SUPPORTO IN AMBIENTE AZIENDALE SU TECNOLOGIA SHARE POINT SERVER 2010 Dipartimento di Ingegneria e Architettura Corso di Laurea Magistrale in Ingegneria Informatica Laureando: Relatore: DOTT. ALEX RONCI DOTT. ING. MAURIZIO FERMEGLIA Correlatore: DOTT. DARIO SOTTANA ANNO ACCADEMICO 2013 - 2014
  • 2. 2 Ad Ornella, Antonello e Thomas
  • 3. 3 1 Introduzione La tesi proposta all’interno di questo documento tratta la progettazione e la programmazione di una struttura di appoggio per gli sviluppatori definita come framework di sviluppo utile alla generazione di un sistema informativo in ambiente CMS (Content Management System) Microsoft SharePoint Server 2010 con cui dare l’opportunità di esulare dall’utilizzo base della struttura di workflow, un modello per la pianifica strutturata di processi programmati, proposta ed implementata dall’azienda di Redmond. Commisionataria del progetto è l’azienda Reply SpA – Cluster di Trieste. L’interesse dell’azienda è quella di avere una struttura più flessibile rispetto quella proposta dalla Microsoft: difatti, come descritta sul loro sito ufficiale, “Workflow is sometimes described as a series of tasks that produce an outcome. In the context of Microsoft SharePoint Products and Technologies, workflow is defined more narrowly as the automated movement of documents or items through a sequence of actions or tasks that are related to a business process”; a quanto si evince, la possibilità di far fluire il materiale a disposizione in maniera non lineare non è contemplata nelle intenzioni originali della piattaforma SharePoint. Questo fatto ci porta ad optare per una soluzione custom che permetta uno scorrere libero lungo tutte le fasi del processo produttivo che si andrà ad implementare nella site collection di interesse. L’obiettivo della tesi dunque risulterà implementare, all’interno di una feature adeguabile ad ogni circostanza similare, un workflow personalizzato a fasi, accompagnato da tutti quei metodi, form ed elementi che possano risultare utili ad un corretto e semplificato sviluppo di una site collection nell’ambiente di riferimento per uno sviluppatore futuro. L’importanza non sarà dunque solamente quella di fornire un prodotto che permetta di scorrere nel processo produttivo, ma che funga primariamente da framework orientato ad agevolare la scrittura di codice da parte di un programmatore che andrà a referenziare tale libreria nella sua soluzione, in modo tale che non debba perdere tempo nello sviluppo di articolati metodi ripetitivi, come possano essere quelli di un passaggio fase, un ritorno ad una fase precedente, alla gestione dei permessi od alla creazione automatizzata di elenchi di servizio interno.
  • 4. 4 Pur nella vastità del progetto, gli elementi che verranno trattati all’interno di questa tesi saranno alcuni di questa libreria, con un occhio particolare su: a) Metodi e classi per lo sviluppo delle funzioni di utility: lo sviluppo di tutte quelle funzionalità base da fornire allo sviluppatore per agevolare il compito di scrittura del codice. Fornire una gamma di metodi più e più volte richiamati all’interno dell’ambiente di sviluppo può portare ad un grosso vantaggio in termini di tempo, e di uniformità di invocazione e gestione di accessi, creazione, modifica delle strutture fornite da Sharepoint. b) Sviluppo logico del workflow: lo sviluppo di una soluzione custom per lo scorrimento in avanti ed indietro nel processo produttivo, tenendo sotto controllo la gestione e controllo dei permessi sugli oggetti coinvolti. Fornire una gestione logica e standardizzata dell’applicazione è importante per semplificare al massimo il lavoro dello sviluppatore che utilizzerà tale framework, e dunque è fondamentale sviluppare le proprie componenti in maniera che siano comprensibili ed adattabili alle più svariate situazioni, rendendole il più possibile generiche. c) Esempi: A completamento del progetto, verranno presentati alcuni casi di implementazione di quello che è stato sviluppato nei punti precedenti, in modo tale da rendere l’idea di come produttivamente possano essere utili le librerie sviluppate. Ovviamente gli elementi che verranno implementati all’interno delle libraries sono possibilmente molti di più, ma probabilmente possono risultare meno interessanti di quelli che sono stati citati, perché meno personalizzati oppure meno salienti rispetto l’obiettivo verso cui protende la tesi stessa, ma sono utili per poter far funzionare appieno tale feature. 1.1 Perché Microsoft SharePoint Server 2010 La scelta di approfondire il progetto in un ambiente professionale come quello di SharePoint Server 2010, piuttosto che la corrispettiva piattaforma Foundation oppure un utilizzo più visuale come quello fornito da SharePoint Designer, è dovuta al fatto di poter operare su di un prodotto più approfonditamente modificabile ed alterabile, in cui un’interfaccia a codice (nel caso di SharePoint C#) possa permettere di intervenire più in profondità sulle strutture di interesse.
  • 5. 5 Da un breve confronto ed analisi dei pro e contro dei vari ambienti di sviluppo, difatti, si può ritenere che la possibilità di personalizzazione di SharePoint può essere così tracciata: se con un utilizzo base, direttamente da interfaccia web, uno sviluppatore (o meglio, in questo caso sarebbe più corretto indicare un utente “collaboratore”) potrebbe andare a caratterizzare approssimativamente un cinquanta per cento delle potenzialità della Site Collection sviluppata, e con il crescere delle capacità e conoscenze ad un circa sessantacinque, solo approdando in un ambiente adeguato (come per esempio SharePoint Designer) potrebbe ottenere dei risultati che si avvicinino al massimo del potenziale. Servono assolutamente degli ambienti di sviluppo (IDE) adeguati (ed in questo caso la migliore è quella fornita direttamente di Microsoft con Visual Studio) e una profonda conoscenza del linguaggio di sviluppo, in modo tale da avvicinarsi prepotentemente alla completa gestione delle potenzialità del CMS. Questo è l’obiettivo ultimo di tale tesi: avere un prodotto più possibilmente performante e generico che possa essere integrato nella maggior parte dei progetti di interesse dell’azienda commisionataria, in modo tale da poter agevolare e alleggerire il carico lavorativo dello sviluppatore, fornendo un framework di supporto nelle più comuni necessità di integrazione tra l’ambiente default fornito da Microsoft e quello personalizzato e maggiormente pertinente al tipo di attività svolte dall’azienda. Il documento qui presente risulterà, in conclusione, diviso in tre parti fondamentali:  Nella prima sezione, verrà trattato il nuovo sistema di workflow, descrivendone le caratteristiche mantenute dalla versione Microsoft e le soluzioni custom proposte in questa tesi, tracciandone principalmente la sua struttura logica e dandone una prima applicazione in produzione caratterizzando le possibili strutture da implementare;  La seconda sezione, quella più corposa, andrà a trattare la composizione della library di metodi che andrà a far da fondamenta per il framework obiettivo di tesi, descrivendone l’architettura e le funzionalità attribuitele, e descritti i metodi forniti al suo interno (con, in alcuni casi, approfondimenti sul flusso logico delle operazioni svolte);  La terza sezione, invece, andrà a fornire un esempio di applicazione delle aree precedenti, con un’analisi del connubio delle varie fasi operative del workflow ed il framework stesso, rendendo così pratica l’applicazione della teoria proposta nei capitoli precedenti
  • 6. 6 Nella parte finale del documento, invece, verranno indicate le possibili espansioni del framework sviluppato, e nelle appendici verranno approfonditi alcuni interessanti temi che vadano a motivare o a esplicare alcune operazioni trattate durante l’intero sviluppo del testo.
  • 7. 7 2 Workflow La prima parte del progetto è quella preposta ad analizzare e sviluppare una struttura di workflow che vada a sopperire alle mancanze, dal punto di vista dell’azienda commissionataria, di quella proposta da Microsoft. 2.1 Breve definizione Il workflow1 è la descrizione di una sequenza di operazioni di un lavoro attribuito ad una persona od ad un gruppo, all’interno di un meccanismo di step che si susseguono senza ritardi uno dopo l’altro, e spesso viene trattato come un’astrazione del lavoro reale, o come rappresentazione di quest’ultimo. Più correttamente, quello che viene esplicitato da noi è quello che viene definito Workflow Management System, un sistema informatico che gestisce ed organizza una serie di tasks per restituire in uscita il risultato del processo produttivo, anche se risulta più semplice definirlo workflow. Gli elementi da tenere in considerazione all’interno di un’attività di un workflow sono: 1. Input: tutte quelle che sono le informazioni necessarie al completamento dello step; 2. Gli algoritmi e le azioni da svolgere, a livello umano o a livello macchina, per completare lo step; 3. Output: tutte quelle informazioni che verranno passate al completamento dello step stesso. 2.2 Workflow in SharePoint Rispettando le linee guida che vanno a definire il flusso, SharePoint2 propone delle soluzioni lineari, orientate all’organizzazione efficace di ruoli e task attivi all’interno del processo, in modo tale da garantire la riduzione ai minimi termini di delay durante i passaggi di consegne, adattandosi al genere di flusso dati richiesto all’interno dell’organizzazione interessata. Come rimarcato anche dalla definizione, il workflow mantiene una struttura lineare e unidirezionale, come esplicitato dai flussi proposti di default in SharePoint: 1 https://en.wikipedia.org/wiki/Workflow 2 http://technet.microsoft.com/library/cc263148(office.14).aspx#WFlowOverview
  • 8. 8  Raccolta commenti e suggerimenti;  Approvazione;  Approvazione dell’eliminazione;  Raccolta firme;  Tre fasi;  Gestione traduzioni;  Gestione problemi. Vi è la possibilità di introdurre dei workflow dichiarativi (quelli descritti in precedenza) oppure compilati, con l’aggiunta di codice personalizzato; tutti conducono ad un flusso ordinato di dati. 2.3 Requisiti Il tipo di workflow richiesto in questo processo ha delle peculiarità:  Possibilità di scorrimento all’indietro nel flusso, in opportuni casi, svincolandosi dalla rigidità del workflow classico;  Organizzazione dei task in macrofasi, di cui è possibile modificarne i contenuti nel momento in cui vi si trova al suo interno. Per l’implementazione, viene lasciata totale libertà di scelta delle strutture su cui far poggiare il flusso in SharePoint, senza richiedere vincoli di utilizzo di DBMS particolari o strutture particolari. Inoltre, viene richiesto di consegnare tutta una serie di funzionalità, metodi che ne permettano un’implementazione efficace all’interno del CMS.
  • 9. 9 Figura 1 - Task 2.4 Specifiche I due requisiti proposti sono legati l’un l’altro, poiché possono permettermi di operare all’interno di un ambiente di workflow pur modificandone parzialmente la logica. Il concetto di task è considerabile come un insieme atomico di azioni da compiere per portare un item dallo stato A allo stato B E le modifiche apportate, giunti nello stato B, risultano permanenti, senza permettere dunque la possibilità di ritornare ad A. Le modifiche da proporre sono dunque legate alla gestione del task ed al susseguirsi logico delle attività da svolgere all’interno del workflow: si è scelto di procedere secondo le logiche descritte in seguito per implementare queste modifiche. 2.4.1 Gestione delle macrofasi Se si vogliono introdurre delle macrofasi, o macro attività, all’interno del workflow, rimandendo coerenti con il suo funzionamento logico, c’è la necessità di stravolgere il concetto di task in quanto tale. Il task non può essere trattato come unità atomica, ma come sequenza di microtasks interni che si susseguono, e comunicanti tra loro i contenuti raccolti nella loro azione. Se ne volessimo fare una raffigurazione grafica, questo sarebbe descrivibile in tal maniera: Figura 2 - Macro Task
  • 10. 10 La struttura avrebbe dunque:  Ingresso al task dall’esterno (freccia arancione in ingresso);  Uscita dal task sia a livello logico (freccia arancione da Task C), sia a livello di dati (freccia gialla da Dati), con unica uscita output. preconfigurandosi, almeno alla visione esterna, con la struttura di una classica attività di workflow. Le modifiche sostanziali sono all’interno:  I dati vengono divisi dalle attività;  Scindendo contenuti e processi, posso suddividere le operazioni in micro-attività, mantenendo condivisi i contenuti fino a quel momento inseriti;  Ogni micro attività avrà a disposizione tutti i dati raccolti nei micro task precedenti, permettendone l’edit di questi, oltre a quelli di pertinenza della fase in questione;  Su ogni micro task, essendo considerati essi stessi task, avranno diritto di azione ruoli diversi (se necessario); Il flusso descritto dalle frecce arancioni traccia il percorso dello stato del workflow, mantenendone l’ordine logico anche all’interno del macro task e marcandone la struttura, mentre quelle gialle tracciano il flusso dei dati raccolti, mostrando come i contenuti siano condivisi all’interno della macro fase, e siano accessibili in lettura e scrittura a seconda dello step in cui vi si trovi. L’attività opera in tal maniera: 1. Il workflow entra nel macro task, come se si trattasse di una comune attività; 2. Vengono definiti i ruoli del primo micro task; 3. L’utente incaricato opera sui dati che può operare nello step in cui si trova; 4. Completata l’operazione, vengono spostati i dati all’interno dell’area condivisa e vengono trasferiti i ruoli all’utente di pertinenza; 5. L’utente subentrante ha la possibilità di operare sui dati vecchi sia su quelli inerenti al suo step; 6. Completata l’operazione, si reitera da 4, finchè non si completano tutti gli step interni;
  • 11. 11 7. Arrivati all’ultimo step, escono sia i dati che lo stato di fase, in modo tale da restituire un valore unico all’attività successiva. Il task così definito può andare a sostituire logicamente quello classico all’interno del flusso, poiché non va ad intaccarne la teoria alla base: se ne mantiene l’orientamento, ma ci permette di operare in istanti diversi su dati che possono essere già stati inseriti in precedenza, senza dover abortire il processo. Il workflow assumerà dunque questa possibile nuova forma: 2.4.2 Gestione del rollback di uno step Secondo passo da analizzare è quello del ritorno ad uno step precedente, concetto non contemplato nella teoria dei workflow. Le problematiche di questo tipo di processo sono dovute a:  Conservazione dello stato del task: se torno indietro, dove mi trovo?  Conservazione dei dati: se torno indietro, i dati inseriti in step successivi dove vanno a finire?  Permessi: se torno indietro, ho ancora accesso agli step successivi, o solamente alla fase in cui si è tornati?  Ruoli: chi ha la possibilità di fare il rollback? Dalla discussione di queste tematiche possiamo ottenere una possibile risposta alla richiesta. Figura 3 - Esempio di Workflow personalizzato
  • 12. 12 2.4.2.1 Stato del task L’operazione di rollback non deve essere evidente ad una visione esterna del flusso, questo per i soliti motivi asseriti nella teoria dei workflow. Quindi deduciamo che la risposta sia: se vi è una rollback, per il workflow devo trovarmi comunque nello stato precedente, così da ovviare a problematiche di gestione e comprensione del flusso stesso. 2.4.2.2 Stato dei dati La conservazione dei dati nel caso di rollback è di articolata gestione, poiché il passaggio da una fase N ad una N-1 comporta 1. Cambiamento dei dati ricevuti in input da N-1; 2. Possibile cambiamento dei dati in input da N; 3. Possibile incompatibilità dei dati inseriti in precedenza in N con i nuovi di N-1 Proponiamo qualche esempio pratico:  In fase N-1 ho inserito un documento, e i dati al suo interno determinato le operazioni della fase N; se torno in fase N-1, ho la possibilità di sostituire tale file, e di conseguenza condizionare le operazioni di N;  Nella fase N respingo i contenuti di N-1, consentendo, con il rollback, la sostituzione di questi ultimi. Avrebbe senso conservare i dati (negativi) di N tornando in fase N-1?  In N eseguo alcune operazioni, ma verifico l’incompletezza (o l’inesattezza) dei dati passati da N-1; se le operazioni svolte in N non sono toccate dalle correzioni, ha senso non conservare i dati fino a lì raccolti?  Se in N-1 ho la possibilità di fare un rollback anch’esso per N-2, dovrei avere condizioni di verifica tali da poter verificare che le sostituzioni possibili in N-2 non abbiano effetto su N-1 e dunque su N. L’elemento di cui tenere primariamente conto dunque è la possibilità di intaccare la correttezza e la consistenza dei dati raccolti dallo step N-m (con m numero di rollback) a N (fase effettivamente raggiunta). Dunque la risposta presa in considerazione è: non risulta efficace conservare i dati delle fasi successive se vi è stato un rollback, per evitare rischi di correttezza dei dati già acquisiti. Le
  • 13. 13 occasioni di avere dei dati non condizionanti, all’interno di workflow, sono molto poche, dunque è difficile che non vi sia incidenza di un task in quello successivo. 2.4.2.3 Permessi La possibilità di operare indistintamente tra più fasi successive può creare dei problemi similari a quelli descritti nel punto precedente: la correttezza del dato resta comunque un cardine di qualsiasi processo informatico, e consentire operazioni parallele su contenuti che possono condizionarsi vicendevolmente può essere pericoloso. Dunque la possibile soluzione è quella di non concedere l’accesso alle operazioni consentite in una fase N, nel caso in cui si torni in una N-1, per le stesse motivazioni date nel paragrafo precedente. 2.4.2.4 Ruoli nel rollback Altro frangente da tenere in considerazione è il tipo di utenza che può operare il rollback del task. Questo deve coincidere con l’utente stesso che ha diritto di operare sul task stesso oppure posso concedere dei permessi speciali ad un utente esterno e sorvegliante il workflow? Consentire l’interazione di utenze esterne all’interno di un task di non propria competenza andrebbe in contrasto con il flusso previsto nella teoria dei flussi: l’utenza opera unicamente sui task di propria competenza. Si possono dunque generare dei task di approvazione dei dati, in modo tale da scindere il rollback dal concetto di approvazione del dato inserito da altre utenze. La risposta a quest’ultimo punto può essere quindi negativa, non consentendo utenti con poteri di rollback esterni a quelli già aventi diritto di processo su di un determinato task. 2.4.3 Definizione delle specifiche Dall’analisi dei punti precedenti, la specifica che ne possiamo trarre fuori avrà questi vincoli:  Il rollback verrà introdotto unicamente all’interno dei macro task descritti in 2.4.1: come illustrato dalle frecce rosse, il flusso all’indietro all’interno del macrotask non genera problemi, per via dei dati condivisi e del non variare dello stato del flusso complessivo del workflow.
  • 14. 14 Figura 4 - Rollback in Macrotask  Il rollback non sarà consentito a cavallo di task non appartenenti allo stesso macro task, per non intaccare la consistenza dei dati;  Il rollback annullerà tutti i dati inseriti nelle fasi successive a quelle in cui ci si trova, per evitare problemi di consistenza dei dati;  Il rollback inibirà l’accesso a tutte le operazioni di fasi successive a quella in cui ci si trova: se torno dal task C al task B, non avrò modo di operare sul task C finchè non avrò nuovamente concluso il task B;  Il rollback non sarà consentito ad utenze che siano esterne a quelle che ne hanno diritto; non è contemplato un utente supervisore che condizioni il flusso. Figura 5 - Rollback tra task diversi Annulla Dati di fase Figura 6 - Eliminazione dati con Rollback
  • 15. 15 Il flusso conserverà tutti i suoi crismi originali, e il nostro lavoro dunque si concentrerà sulla gestione dei macro task e sulla rispettiva strutturazione in ambiente SharePoint, esulando dalla struttura di default proposta da Microsoft. 2.4.4 Specifiche accessorie Oltre a comprendere quali siano le soluzioni per i due requisiti, è importante definire e comprendere quali siano le specifiche di contorno utili al progetto: 1. Interfacce che permettano la visione globale e precisa di workflow ed istanze di queste; 2. Nel caso di istanze di workflow, elementi di gestione di flusso tra le varie fasi, sia in caso di passaggio tra fasi interne ad un macrotask, sia nel caso di flusso da un task ad un altro, quali ad esempio pulsanti complementari a quelli di default; 3. Possibilità di visionare ed editare i dati di fasi precedenti interne al proprio macrotask senza che questi si mescolino / non siano evidenti all’interno del task di propria competenza. In tal maniera abbiamo una descrizione a tutto tondo di quello che ci servirà per definire e rendere il workflow comprensibile e gestibile all’utente finale. Task completato Task in esecuzione Rollback Task C A B C A B C A B C Task A completato Completo task B Task non eseguibile Figura 7 - Inibizione di accesso a dati futuri con Rollback
  • 16. 16 2.5 Progettazione Basilare è scegliere come organizzare il workflow, definendo su quale delle possibili strutture dati gestire il flusso. Allora sarà da specificare come implementare lo scorrimento tra le fasi e tutto ciò che va a circondare questi processi. 2.5.1 Gestione dei dati nelle macrofasi Lo step è trovare una struttura logica che ci permetta di gestire la condivisione delle informazioni tra task successivi ed appartenenti alla stessa macrofase. Non è possibile gestire nelle modalità proposte da un workflow classico, poiché i dati caricati in precedenza sarebbero accessibili solo per approvazione, e non in edit (tornando cioè alla conformazione di task distinti e non aggregati). L’ipotesi che si va a proporre dunque contempla una gestione condivisa dei dati stessi, tramite un insieme (ipotizzabile in forma tabulare) aggregato di informazioni suddiviso per sottoaree, accessibili a seconda del task in cui ci si trova. Con una rappresentazione grafica, si può ipotizzare un frammento all’interno di una macrofase in questo modo descritto: In tale modo l’utente del task avrà almeno accesso in lettura ai dati delle fasi precedenti, se non addirittura in scrittura (dipende dal ruolo dell’utente coinvolto), potendo dunque gestire e motivare il rollback (ad esempio, correzione dei dati inseriti in precedenza), ed allo stesso tempo operare su dati inseriti in precedenza senza arrecare inconsistenza nei dati. Dati Task A Dati Task B Dati Task C Task A Task B Task C Figura 8 - Dati condivisi in macrotask
  • 17. 17 2.6 Scelta della struttura dati La struttura, tra quelle disponibili in SharePoint, più similare a quella proposta, anche se può sembrar banale, è quella della lista. Questo perché:  È un insieme ordinato di oggetti in cui si può accedere alle varie colonne in modo guidato, tramite le form;  Permette di avere un aggregato dei dati della macrofase, associato in modo univoco ad un item, che è il nostro flusso;  Posso relazionare più liste (e dunque più macro task) tra loro inserendo un identificativo univoco e condiviso tra le varie liste, in modo tale da tenere traccia dell’evoluzione del flusso.  Posso inserire un parametro di fase, che mi identifichi in quale stato si trovi il macrotask al momento del salvataggio, in modo tale da poter gestire di conseguenza i permessi associati all’item. Scegliere un’altra struttura, come ad esempio quella della Document Library, rendere il tutto decisamente più complicato a livello di organizzazione:  Sarebbe da organizzare una folder della DL per ogni flusso interessato, e le relative subfolder create ad ogni passaggio di macrotask, cosa che invece con un insieme di liste (già definito) porterebbe alla sola aggiunta di un item con identificativo univoco già creato;  Problemi sui permessi: ogni volta che creo una cartella dovrei configurare i permessi su essa e poi su tutti i suoi contenuti, non avendo un parametro di controllo facilmente condivisibile;  Problemi nella ricerca: dovendo attingere a delle cartelle, non ho la certezza di avere i dati di cui sono interessato (potrebbero essere in eccesso o mancarne alcuni);  Problemi nel confronto dei dati: dovendo pescare da folder distinte, dovrei fare un’analisi gerarchica all’interno di queste, verificando fino a che punto si sia giunti, per poi raccogliere i dati; nel caso di una lista, vedo direttamente tramite una view quello che mi interessa;  Gestione dei requisiti: Organizzo delle subfolder nelle subfolders? Avrei dei problemi a sul piano del macrotask (i documenti non sarebbero condivisi, aprendo criticità a livello
  • 18. 18 di permessi). Organizzo tutto in una cartella comune? Avrei problematiche nella distinzione dei file nelle varie microfasi; Allo stesso modo, l’introduzione forzata di una struttura come i Document Set risulterebbe maggiormente articolata (la banale installazione della feature associata costringerebbe ad avere una site collection compatibile con quest’ultima) e non così efficace rispetto a quelli che potrebbero essere i profitti: anche in questo caso ci troveremmo di fronte ad una struttura atta a gestire documenti, non tanto a dati, riportandoci ai problemi definiti per la Document Library. Dunque, la strutturazione del workflow a macrofasi tramite liste risulta essere la soluzione più efficace e completa per le nostre finalità: potremo apprezzare nei capitoli successivi come questa via risulti adeguata.
  • 19. 19 3 Library SharePoint Utilities La seconda sezione del nostro progetto va a trattare il package che va a fornire le funzioni di estensione più comuni per il tipo di progetti creati nell’azienda, e di appoggio al workflow trattato nel capitolo precedente. L’obiettivo primario è quello di fornire metodi utili ed efficaci al futuro programmatore in modo tale che non debba scrivere del codice ripetuto, ripetitivo e spesso utilizzato all’interno di un qualsiasi progetto. Rispettando un concetto di chiarezza e semplicità all’interno del package, è importante anche suddividere il prodotto sin dall’interno in feature, per mostrarne le diverse funzionalità e permetterne l’utilizzo distinto a seconda dei casi. Essendo un modulo di generics, è molto utile poter far scegliere al programmatore quali funzionalità importare all’interno del proprio progetto, consentendo una scelta che non vada ad inibire l’utilizzo di una o l’altra funzionalità. Oltretutto, la creazione di un numero maggiore di feature consente una migliore gestione del debugging, poiché rende possibile ridurre le problematiche ad un pacchetto più piccolo e più facilmente controllabile. 3.1 Requisiti Il prodotto, in questa parte del progetto, deve soddisfare le richieste del workflow, dunque consentire la gestione di:  Gruppi Utenti  Document Libraries  Liste di Configurazione  Elenchi  Mail A cui, inoltre, associare la configurazione di WebPages all’interno dell’ambiente SharePoint, la gestione degli accessi in modalità di manutenzione della piattaforma in utilizzo, e fornire tutti i possibili metodi di supporto per un corretto funzionamento dei metodi richiesti.
  • 20. 20 3.2 Analisi funzionale L’organizzazione logica della solution è già descritta dalle specifiche. Si necessita dunque di due features separate, pur appartenenti allo stesso prodotto, per lo sviluppo del software e per la gestione della manutenzione della site collection. Per l’area di sviluppo, i requisiti indicano aree di sviluppo (sei) distinte tra di loro: la soluzione più ovvia e mantenere questa configurazione pure all’interno della feature, consegnando una classe per ogni tipologia di componente da implementare. Si è dunque andati a definire sei classi che si distinguano per i metodi forniti: 1. DocLib per la gestione delle document libraries; 2. Groups per la configurazione dei gruppi; 3. KeyValList per le liste di configurazione; 4. Lists per la creazione di liste; 5. Mailer per fornire i servizi di mail al workflow; 6. PubManager per le pagine di pubblicazione da interfaccia A questi dunque sono stati associati quei metodi comuni e necessari in ogni loro situazione. Primariamente sono state dunque considerate 4 classi accessorie, che vanno a vertere su due tematiche distinte, le security e il logging, e importate con queste modalità: Figura 9 - Strutturazione funzionale della library
  • 21. 21 Il principio alla base delle classi accessorie si mantiene lo stesso di quello utilizzato nelle altre classi: assegnarne una per categoria di funzionalità permette di distinguere immediatamente ciò che viene fornito, semplificando allo sviluppatore la comprensione della struttura a disposizione. Per l’area di manutenzione, invece, i requisiti indicano una sezione di controllo degli accessi alle operazioni disponibili. L’idea proposta è quella di introdurre un prefiltraggio alle pagine a cui accedere, nel caso in cui la feature sia attivata. Proporre dei metodi, in questo caso, può risultare inefficace, poiché sarebbe poi da trovare delle modalità per far passare tutte le pagine in prefiltraggio per questi, costringendo gli sviluppatori ad inserire una chiamata al metodo in un qualsiasi Page Load, non sempre disponibile oltretutto. Si può preferire dunque la creazione di un ascx che funge in forma delagata all’apertura di ogni pagina, così da inserire un controllo in questo preciso istante: questo va ad alleggerire il carico sullo sviluppatore, che può completamente dimenticarsi la gestione di tale frangente, ed occuparsi unicamente della scrittura del codice inerente alle funzionalità della pagina di interesse. Questa feature dunque sarà configurata in modo tale da fornire al solo gestore della site collection ed agli amministratori la possibilità di attivare questa funzione (anche perché sarebbero gli unici interessati ad averne accesso), e dunque attivabile per via interfaccia a seconda della situazione. Quello che si va ad ottenere, e che andremo a descrivere in seguito, è dunque una struttura con due feature, le Utilities e la BlockUsers, attivabili in maniera distinta e indipendenti l’una dall’altra, cosicchè ogni site collection abbia la possibilità di scegliere se attivare o meno tali funzionalità fornite. 3.3 Feature Utilities La prima feature sviluppata comprendere gli effettivi metodi di utilities che vanno a soddisfare i requisiti di questa porzione di progetto.
  • 22. 22 3.3.1 Classi 3.3.1.1 DocLib La classe DocLib contiene quei metodi che vanno ad essere di supporto alla generazione delle Document Libraries di nostro interesse. Al suo interno sono stati sviluppati, al momento, 5 metodi “principali”, con alcuni metodi accessori di controllo. 3.3.1.1.1 SPList Create Questo metodo va a generare una Document Library all’interno del site di interesse. Ha come parametri di input questi argomenti: o SPWeb web: è l’url del WebSite di interesse o String name: è il nome da associare alla Document Library o String description: è la descrizione da associare alla Document Library o Boolean? displayOnQuickLaunch: è il valore di controllo per far visualizzare la Document Library sulla Quick Launch Bar del WebSite. Il diagramma di flusso del metodo è molto semplice: Figura 10 - Flusso SPList Create
  • 23. 23 Il percorso illustra come gli argomenti di input influiscano direttamente sul procedere dello stesso. Importante è avere definiti entrambi i parametri per eseguirne correttamente il list.add all’interno del WebSite, che va a restituire la GUID della lista creata, su cui poi poter configurare la property di visibilità nella quickLaunch. Il list ed il web Update vanno a consolidare le modifiche svolte, a chiusura del metodo, restituendoci la lista stessa come output. Nel caso di malfunzionamento, il metodo va in catch e da un log di report. 3.3.1.1.2 Void MoveAttFile Questo metodo permette il trasferimento di un documento da una Document Library ad un’altra. Gli argomenti in input sono: o SPWeb web; o String listName: è il nome della Document Library da cui attingere; o String oldStringUrl: è il percorso da dove proviene il documento da trasferire; o String fileName: è il nome del file da trasferire; o List<String> folderListLevel: è l’elenco delle folder del percorso per giungere alla folder in cui spostare il documento; o Boolean forceElevatedPrivileges: permette, a seconda del valore settato, di operare o no con i permessi da amministratore; o Out String url: è l’url di uscita del file trasferito Il metodo va a richiamarne un altro omonimo, con gli stessi input (tranne la gestione dei permessi elevati), che esegue il processo vero e proprio: 1. In un boolean viene salvato lo stato dell’AllowUnsafeUpdates; 2. Lo stato del web.AllowUnsafeUpdates viene settato a false, per poter operare senza problemi questo processo di trasferimento; 3. Viene richiamato il metodo EnsureFolders per verificare che il path assegnato sia realmente esistente, dandocene l’url (lo approfondiremo nella descrizione del metodo stesso); 4. Viene recuperato l’SPFile tramite l’oldFileUrl;
  • 24. 24 Figura 11 - Flusso insertFile 5. Tramite il metodo dell’oggetto MoveTo, quest’ultimo viene spostato nel nuovo path con il fileName assegnato; 6. Viene generato l’url definitivo, che verrà poi restituito come output del metodo; 7. Viene ripristinato lo stato iniziale dell’AllowUnsafeUpdates. Anche in questo caso viene configurato un try / catch in modo tale che possa intercettare gli errori di inserimento dei file nelle varie cartelle, verificando l’unicità di tale documento e l’effettiva trasferibilità dello stesso. 3.3.1.1.3 Void InsertFile In maniera similare al precedente, questo metodo va a creare un file all’interno della Document Library di interesse. Gli argomenti del metodo sono: o SPWeb spWeb; o String listName; o Stream fileStream: è lo stream del contenuto del documento da creare; o String fileName;
  • 25. 25 o Boolean overwrite: bool per la gestione della sovrascrizione dei file con stesso fileName nella stessa lista; o List<String> folderLevelList; o Boolean appendNewGuid: bool per assegnare un nuovo GUID all’oggetto che si va a creare; o Out String url. In questo caso, dopo aver configurato o meno i permessi elevati per creare il file, viene anche effettuato l’overload di tale metodo, andando a seguire il flusso nella figura precedente. Il risultato è quello di salvare l’url relativo del file appena creato all’interno della variabile url, consegnatoci funzionante dal try / catch di controllo; nel caso di malfunzionamenti, verrà generata un’eccezione e restituito un url vuoto. 3.3.1.1.4 Void DeleteFile Al contrario del metodo precedente, questo andrà a rimuovere il file indicato. Come parametri di input avrà difatti, oltre al classico spWeb, l’url del file e il boolean forceElevatePrivileges. A seconda del forceElevatedPrivileges, il metodo accederà o no in un SPWeb con i privilegi da amministratore, per poi fare un spWeb.GetFile(url) e rimuovere questo. 3.3.1.1.5 Metodi di controllo A supporto dei metodi descritti in precedenza, abbiamo tre metodi di controllo dei file names ed uno per il controllo del path di destinazione dei file. 3.3.1.1.5.1 File Name Questi tre metodi servono a ripulire i nomi dei file che verranno caricati a livello programmatico all’interno di Lists e Document Libraries, in modo tale che queste ultime possano accettarli senza avere alcuna generazione di errore. Il fatto di non aver errori a livello di caricamento di file creati è fondamentale per poter evitare documenti rotti o spezzati. 3.3.1.1.5.1.1 Boolean CheckLengthFileName Verifica la lunghezza della stringa in input. Restituisce true se la lunghezza di tale è minore di una costante definita nella classe.
  • 26. 26 3.3.1.1.5.1.2 Boolean checkFileName Verifica la correttezza del nome del file, controllando l’assenza di caratteri speciali all’interno della stringa in input. Restituisce true nel caso venga superato il controllo. 3.3.1.1.5.1.3 String CleanFileName Ripulisce il filename dai caratteri non ammessi, nel caso vi fossero, e accorcia la lunghezza del file ad un valore pari alla costante definita nella classe, in modo tale da essere caricabile all’interno delle strutture di interesse. 3.3.1.1.5.2 Path Il controllo sul percorso in cui andare a inserire è importante quanto la corretta definizione del nome del file stesso. Cercare di mettere un documento all’interno di uno spazio non esistente apporterebbe degli errori non indifferenti, primariamente nella creazione ed inserimento del documento stesso, poi perché andrebbe ad inficiare sul flusso dei dati di nostro interesse. Per questo motivo è stato sviluppato il seguente metodo. 3.3.1.1.5.2.1 Void EnsureFolders Questo è il metodo di appoggio più interessante, poiché va a verificare l’esistenza delle folder del percorso del file che si andrà a creare (spostare), in tal modo da aver effettivamente una folder in cui porre quest’ultimo. Il diagramma di flusso del metodo è quello descritto nella pagina successiva.
  • 27. 27 3.3.1.2 Groups La seconda classe che verrà analizzata è quella dei gruppi: all’interno di questa sono stati implementati tutti quei metodi che portano alla creazione, eliminazione e verifica dei gruppi all’interno della site Collection di nostro interesse. 3.3.1.2.1 SPGroup Create Il metodo va a creare un nuovo gruppo all’interno della Site Collection, segnalando errore nel caso, ad esempio, questo già esista. Non è necessario l’accesso con permessi elevati, poiché tali operazioni si presume possano essere utilizzate unicamente da utenze già abilitate con tali ruoli. Gli argomenti di input sono: o SPWeb spWeb; Figura 12 - Flusso ensureFolders
  • 28. 28 o String spGroupName: Il nome da assegnare al gruppo; o String spGroupDescription: la descrizione del gruppo; o SPMember groupOwner: l’owner del gruppo che si va a creare; o SPRoleDefinition spRoleDefinition: il ruolo assegnato di default al gruppo all’interno della Site Collection. Il flusso del metodo è così descrivibile: Allo stesso modo, vi è un metodo in overload che invece di prendere il parametro SPRoleDefinition ha come argomento un SPRoleType: questo richiama il Create con spRoleDefinition = spWeb.RoleDefintions.GetByType(roleType) 3.3.1.2.2 void CreateIfNotExistsPermissionLevel Il metodo qui descritto va a verificare l’esistenza di un livello di permessi da poter assegnare, in seguito, ad un determinato gruppo: se questo non esistesse, verrà creato. Argomenti richiesti sono: o SPWeb spWeb; Figura 13 - Flusso SPGroupsCreate
  • 29. 29 o String permissionLevelName: il nome del livello di permessi che si intende verificare; o String permissionLevelDsc: la descrizione del livello, nel caso se ne creasse uno nuovo; o SPRoleType: il ruolo associato a questo livello, nel caso se ne creasse un nuovo Il codice è di per sé particolare: sfruttando il try / catch come se fosse un if, nel caso non esistesse il tipo di permesso associato al permissionLevelName, all’interno del catch sia andrà a definire quest’ultimo, con nome, descrizione e ruolo. In caso di funzionamento corretto, non verrà eseguito alcunchè. 3.3.1.2.3 Void FindGroupToDeleteToCreate Questo metodo accessorio permette di restituire un elenco (nuovo) di gruppi da eliminare e di popolare un’altra list con quelli da creare, verificando tra quelli già esistenti. Input del metodo sono: o SPWeb spWeb; o SPGroupCollection spGroupCollection: è la collezione di gruppi da controllare; o Ref List<String> newGroupNameList: l’elenco dei gruppi da aggiungere (è una lista già preesistente passata dal processo invocante) [è fondamentale che questo elenco sia ordinato alfabeticamente]; o Out List<String> spGroupListToDelete: è l’elenco dei gruppi da rimuovere; Il metodo controlla di non aver già analizzato per intero i contenuti della collection di gruppi spGroupCollection e la lista dei nomi newGroupListName. Se così fosse, entra in un secondo ciclo while che confronta i nomi dei gruppi presenti. Il compare dei nomi serve proprio a questo: nel caso il gruppo seguisse nell’ordine un gruppo già presente, visto l’ordinamento alfabetico di entrambe le liste, andrebbe ad implicare l’inutilità del gruppo sopra citato, e dunque avente diritto ad entrare immediatamente nelle liste da cancellare. Nel caso invece i due nomi coincidessero (dunque il compare tra newGroup e spGroup risultasse pari a 0), il newGroup non sarebbe da aggiungere, e dunque andrebbe rimosso dall’elenco dei nomi “nuovi”.
  • 30. 30 Ad ogni passaggio viene verificato che la collection spGroupCollection abbia un valore maggiore a quello del suo counter (sennò finirebbe immediatamente il processo in atto); superati i while, dunque, avremmo le liste popolate in maniera da avere i gruppi non esistenti da una parte, quelli da rimuovere dall’altra. A completare il ciclo, vengono verificati gli ultimi Gruppi che non siano stati confrontati: questi stessi verrebbero spostati nella lista dei gruppi da rimuovere, e mandato dunque, alla fine del for, il processo in chiusura. Il diagramma di flusso è: Figura 14 - Flusso FindGroupToDeleteToCreate
  • 31. 31 Come sottolineato, l’ordinamento alfabetico è trascendentale per il corretto funzionamento del metodo: se andassimo ad operare su di un elenco non ordinato, il metodo di controllo si sfalderebbe al primo gruppo non ordinato, e dunque andremmo a rimuovere gruppi da mantenere oppure ad aggiungere gruppi già esistenti, andando incontro ad un’inevitabile crash. 3.3.1.2.4 Boolean hasCurrentUserAPermissionLevel Il metodo in questione verifica se un determinato utente ha almeno un livello di permessi all’interno della site Collection presa in considerazione, e torna true nei casi in cui soddisfi questa richiesta, oppure sia siteAdmin. Questo metodo poggia su di un altro presente in questa classe, il isPermissionLevelInRoleAssignment (che verrà descritto in seguito), ed ha come parametri di input il classico spWeb e l’elenco di string permissionLevelsName di cui verificare la presenza. In questo caso, per poter verificare i permessi, necessitiamo di un accesso con privilegi Elevati. Il metodo si comporta in questo modo: 1. Viene settato a false il valore da mandare come output del modulo; 2. Viene creata una chiave per tutti i gruppi che contengono lo user preso in considerazione, e la metto all’interno del dictionary groupUserHasAccess; 3. Viene creato l’ambiente per operare con i privilegi elevati; 4. Si verifica se è admin della site Collection: se si, ritorna true; 5. Se non passa la verifica, viene generata una spGroupCollection dei gruppi presenti sulla site Collection, ed un SPRoleAssigmentCollection dei permessi presenti sulla stessa; 6. Per ogni gruppo della spGroupCollection viene lanciata una query linq in cui si verifica se vi è un record che appartenga alla dictionary e che abbia lo stesso Group.ID; 7. Se sì, si verifica il gruppo abbia uno dei livelli permessi elencati all’interno del permissionLevelsName: in caso affermativo, setto il valore di output a true e faccio un return di quest’ultimo; 8. Nel caso non risultasse alcun permesso associato ai gruppi, vi sarebbe un’ulteriore verifica, tramite il metodo isPermissionLevelInRoleAssignment, rispetto al singolo
  • 32. 32 utente: con lo stesso ragionamento proposto al punto 7, se verrà riscontrato almeno uno dei permessi richiesti, verrà ritornato true; 9. Nel caso si giungesse a questo punto, il metodo ritornerà false. Il tutto permetterà di ovviare a dover passare per via di interfaccia alla scansione dei permessi di un utente all’interno di una site Collection. Allo stesso modo, è stato implementato un ulteriore metodo in overload che, oltre a restituire il booleano, rende in out l’elenco dei gruppi in cui lo user ha i permessi ricercati. 3.3.1.2.5 Boolean isPermissionLevelInRoleAssignment Quest’ultimo metodo della classe ci permette di verificare se un RoleAssignment contiene uno dei RoleDefinitionBindings presenti all’interno della lista di permessi passata in input. Presi come argomenti: o SPRoleAssigment spRoleAssigment: è il ruolo da verificare o String[] permissionLevelsName: è il nome dei permessi da verificare Verranno estratti i livelli di permesso associati all’spRoleAssigment, e per ognuno di questi attuato un compare del loro nome con le stringhe: in caso affermativo, il metodo restituirà true.
  • 33. 33 3.3.1.3 KeyValList La terza classe in oggetto è quella che consente una generazione rapida di liste di Configurazione da associare alla site Collection, generando, di principio, una lista strutturata come un dictionary con key e value. I metodi di questa classe risultano fortemente correlati tra loro: dunque, per agevolare la comprensione di questi, non verrà seguito un ordinamento alfabetico, ma piuttosto verrà seguito, dal basso verso l’alto, l’ordine di incapsulamento di questi, descrivendo quelli che poi verranno richiamati all’interno degli altri. 3.3.1.3.1 Bool TryAddKey Il metodo in oggetto va ad aggiungere un nuovo item nella lista di nome listName con chiave key e valore value. I parametri di ingresso sono: o SPWeb spWeb; o String listName; o String key; o String value; Il metodo esegue una query linq all’interno della lista, e verifica che non vi sia già un item con key identica a quella passata. In conclusione, il flusso sarà il seguente: Figura 15 - Flusso TryAddKey
  • 34. 34 3.3.1.3.2 void CreateKeyValueListNoPrivileges Questo metodo permette la generazione effettiva della Lista di Configurazione all’interno della propria site Collection, con la generazione della stessa in caso di necessità, e di popolamento tramite il dictionary passato. Argomenti del metodo sono: o SPWeb web; o String listName; o Dictionary<String,String> keys: è l’elenco di chiavi da inserire all’interno della lista; o KeyValueListPermissions permissions: è il tipo di permessi da assegnare alla lista Quest’ultimo type è generato appositamente per la classe in questione, permettendo la gestione dei permessi in modalità ereditata dall’ambiente oppure Admin only. La funzione verifica se la lista di configurazione non sia già esistente, tramite l’utilizzo particolare del try/catch, e dunque va ad inserire, nella lista esistente (o creata dal metodo stesso) il dictionary passato in input, controllandone l’univocità dei parametri passati. Questo va ad esplicitare il funzionamento del try / catch: nel caso di non esistenza della lista, la funzione andrebbe in errore, ma il catch, come da corretto funzionamento, cattura questo scatenando la creazione della lista stessa ed andando a popolarlo di conseguenza. La pulizia dei permessi tramite il tipo KeyValueListPermissions permette inoltre di tutelare i contenuti della lista stessa da modifiche indesiderate da parte di utenze in teoria non abilitate. Il diagramma di flusso è dunque il seguente:
  • 35. 35 Figura 16 - Flusso CreateKeyValueListNoPrivileges 3.3.1.3.3 Void CreateKeyValueList Questo è il metodo che va a richiamare il precedente per poter funzionare. Ricevendo come input: o SPWeb web; SPList spList = web.Lists[listName] try Visitata tutta la dictionary Log dell’add riuscito TryAddKey Generazione della Lista di Configurazione noCrawl = true spDefaultView.ViewFields.Add(VALUE_FIELD_NAME) try Visitata tutta la dictionary Add dell’item Permissions = ONLY_SCA Rimuovi tutti I permessi sulla lista Log di errore di creazione VERO VERO FALSO FALSO CATCH E CATCH E FALSO FALSO VERO VERO
  • 36. 36 o String listName; o Dictionary<String,String> keys; o KeyValueListPermissions permissions; o Boolean forceToElevatePrivileges Questo prepara, a seconda del valore di forceToElevatePrivileges, l’ambiente in cui invocare il CreateKeyValueListNoPrivileges, passando come parametri quegli stessi ricevuti come argomenti alla rispettiva invocazione, senza operarne alcuna modifica. 3.3.1.3.4 String GetValueFromKeyNoPrivileges Seguendo la strutturazione dei metodi precedenti, questo va ad essere il “nucleo operativo” dell’operazione di ricerca della key e di restituzione del rispettivo value. Ricevendo come argomenti: o SPWeb web; o String listName; o String key: è il parametro della chiave da ricercare; o Out SPListItem item: è l’item su cui salvare la ricerca. Questo pesca la key in questione all’interno della lista definita con listName, passa l’item ritrovato in out e restituisce il value dell’item stesso. 3.3.1.3.5 String GetValueFromKey Come il metodo CreateKeyValueList, quest’ultimo prepara l’ambiente per invocare il GetValueFromKeyNoPrivileges, a seconda del bool che riceve in argomento: o SPWeb web; o String listName; o String key; o Out SPListItem item; o Boolean forceToElevatePrivileges. Allo stesso modo esiste un metodo overload senza l’argomento out SPListItem: in questo caso ne viene generato uno in locale e passato come argomento per invocare il metodo GetValueFromKeyNoPrivileges.
  • 37. 37 3.3.1.3.6 Void SetOrAddValueNoPrivileges Ricevendo come parametri di ingresso: o SPWeb web; o String listName; o String key; o String value Questo verifica (tramite query linq) se è già presente un item con quella key, ne crea uno se non esistente, e dunque setta il valore del campo VALUE con quello passato in ingresso. 3.3.1.3.7 Void SetOrAddValue Come per i metodi precedenti, anch’esso genera l’ambiente con o senza privilegi elevati per eseguire il SetOrAddValueNoPrivileges. 3.3.1.4 Lists Questa quarta classe ha un comportamento e dei metodi similari a quelli proposti all’interno della DocLib class, poiché invece di operare su di una Document Library, operiamo su di una Lista, che, dal punto di vista di SharePoint, risultano essere delle strutture similari tra loro. Prima di iniziare a descrivere i metodi, è da analizzare la classe introdotta al suo interno, per il tipo Field, utile per la gestione del tipo di campo da inserire in una lista. 3.3.1.4.1 Class Field Questo type è costituito da 4 properties e due costruttori, così definiti:  SPFieldType Type: definisce il tipo di campo da inserire nella lista;  Bool Required: impostazione dell’obbligatorietà sul campo;  Bool AllowMultipleValues: configurazione della possibilità di più valori per il campo in questione;  String[] Choice: i possibili valori associabili al campo stesso I costruttori invece si differenziano nella gestione dei campi AllowMultipleValue e Choice: 1. Il primo costruttore definisce le possibili choices all’interno dell’oggetto 2. Il secondo definisce se è possibile un valore multiplo per lo stesso
  • 38. 38 3.3.1.4.2 SPListItem CopyItemTo Questo metodo permette la copia di un item da una lista ad un’altra che abbia almeno i campi di questo già definiti al suo interno. Come argomenti abbiamo: o SPListItem item: è l’item da copiare; o SPList destinazione: è la lista di destinazione; o SPFolder allegati: è la cartella che comprende gli allegati da copiare Il metodo opera in questo modo: 1. Viene creato un nuovo item nella lista di destinazione 2. Per ogni field all’interno dell’item, viene verificato che non sia un readOnlyValue, non sia un campo calcolato e non sia uno dei campi built-in delle liste di SharePoint, e verifica che un campo con quel nome esista effettivamente 3. Se supera il test al punto sopra, inserisce il valore all’interno del campo di pertinenza, e ripete 2. finchè non ha verificato tutti i campi dell’item; 4. Per ogni attachment passato, ne recupera l’oggetto fisico (tramite l’url dell’item di origine); 5. Ne apre un array di byte; 6. Lo allega all’item nuovo, e ripete da 4 per tutti gli attachments; 7. Rimuove tutti i permessi del nuovo item; 8. Prelevando i ruoli dall’item di origine, li trasferisce al nuovo; 9. Per tutti gli allegati dell’SPFolder li trasferisce associandoli all’item stesso; 10. Restituisce il nuovo item. 3.3.1.4.3 SPListItem MoveItemTo Il metodo opera in maniera similare al precedente. Unica differenza è l’eliminazione dell’item di origine alla fine della funzione. 3.3.1.4.4 SPList Create Consente la generazione, in modalità diverse, delle liste. È un metodo in overload, con 4 signature diverse. Argomenti in comune sono: o SPWeb web; o String name: il nome della lista da creare
  • 39. 39 Mentre a differire è il modo in cui vengono passati i tipi di campo all’interno della lista stessa: 1. Dictionary<String,Fields> fields Dopo aver creato una nuova lista generica con il nome passato in input, viene analizzato il dictionary in tale modo: È importante notare che i campi SPFieldChoice e SPFieldUser debbano avere un percorso stante a se stesso poiché sono gli unici che richiedono dei parametri particolari (le possibili choices in un caso, l’AllowMultipleUser nell’altro) da inserire. Gli altri necessitano unicamente, nel nostro interesse, del solo nome di campo, il tipo dello stesso ed il boolean per la configurazione dello stato required. 2. List<SPFields> fields In questo caso i campi sono già strutturati, perché la lista riceve dei tipi di campo. Dunque la funzione si riduce ad aggiungere alla vista il campo e configurarne il suo tooltip, definendone la possibilità di visualizzazione in tutte le possibili form della lista stessa. Tutte le complicazioni illustrate in 1. non vi sono poiché i campi non devono essere creati ex- novo. Fields[nomeCampo].type SPFieldChoice scelta Choice != null Aggiungi scelte possibili SPFieldUser user MultiUser == true Consenti MultiUser Aggiungi alla lista Aggiungi alla lista con i parametri necessari Aggiungi il campo alla vista di default Tipo SPFieldChoice Tipo SPFieldUser Altri Tipi VERO VERO FALSO Figura 17 - Flusso Create
  • 40. 40 3. String contentTypeId, SPListTemplateType listType Con questa signature l’idea è quella di permettere la generazione di una lista con template di base definito dall’utente e settarne il relativo content type tra quelli disponibili. Il content type permette di definire il metedata ed il behaviour per un determinato data entity, a cui sono associati i relativi workflow, policy, site columns.3 Il metodo opera in tale maniera: i. Viene generata la lista; ii. Per la lista viene abilitata l’associazione dei content types (list.ContentTypesEnabled); iii. Viene creata un elenco toDelete dei content types da rimuovere recuperando tutti quelli già associati alla lista stessa; iv. Viene generato un nuovo Content type definito tramite la stringa contentTypeId; v. Vengono rimossi tutti i content types dell’elenco toDelete associati alla lista in questione Come oggetto in uscita abbiamo la lista stessa creata 4. String contentTypeId Quest’ultimo si rifà al metodo descritto in 3., con l’unica eccezione che il il template della lista è predefinito in SPTemplateListType.GenericList. 3 http://msdn.microsoft.com/en-us/library/ff798404.aspx come riferimento e descrizione riguardo il Content type di una lista o document Library
  • 41. 41 3.3.1.5 Mailer La classe mailer è tra le più importanti, se non la più importante tra quelle sviluppate. Il metodo di gestione della mail in SharePoint funziona in maniera similare ai classici event handler esistenti: può essere integrata la sua gestione all’interno di un workflow o ad un qualsiasi evento di alert, ma non a degli eventi custom operativi a prescindere. Questo è lo scopo del mailer proposto: fornire dei metodi che garantiscano, indipendentemente dalla struttura a workflow o da eventi scatenati dal sistema stesso, la gestione della mail, i relativi contenuti, i mittenti ed i destinatari in modo più autonomo e libero possibile. Essendo poi la società orientata a non sfruttare la struttura di workflow proposta, è fondamentale una gestione esterna di tali processi, in modo tale da poter usuffruire ugualmente di un servizio che risulta sempre più importante nella pianificazione, sviluppo e gestione di un ciclo produttivo industriale in maniera completa ed efficiente. Dunque, la classe fornirà primariamente 4 diversi metodi, ed un costruttore di classe per definire il tipo EmailTemplate, che descriverà subject e body della mail stessa. È inoltre interessante notare che, a differenza di tutte le altre classi, gli import da package esterni è molto più vasto, specie per poter consentire l’uso di server SMTP per l’invio delle mail stesse. Gli import eseguiti sono: o System.Net4: permette di avere metodi di gestione dei protocolli di comunicazione su reti o System.Net.Mail5: è il namespace che permette la gestione dell’invio dei messaggi tramite il server SMTP; o System.Collections.Specialized6: namespace che permette una gestione di raccolte particolarmente specializzate o tipizzate 4 http://msdn.microsoft.com/it-it/library/system.net.aspx 5 http://msdn.microsoft.com/it-it/library/system.net.mail.aspx ne descrive metodi e funzioni 6 http://msdn.microsoft.com/it-it/library/system.collections.specialized.aspx
  • 42. 42 o Microsoft.Sharepoint.Administration7: namespace che permette una più vasta gestione dei tipi e membri da configurare durante il deploy; o Microsoft.Sharepoint.Utilities8: comprende un insieme di metodi per una più pratica gestione della piattaforma SharePoint; o System.Web.UI.WebControls9: consente la creazione di controlli server all’interno di una pagina web, risultando necessario nel caso di utilizzo del metodo all’interno di ulteriori event handler. 3.3.1.5.1 Class EmailTemplate È strutturata in maniera molto semplice: o Una stringa pubblica di Subject; o Una stringa pubblica di Body; o Un costruttore di classe che setta i due valori definiti in precedenza 3.3.1.5.2 Void createEmailTemplateList Questo metodo è utile a preparare l’ambiente per la gestione delle mail all’interno della site collection, definendo la lista di appoggio in cui vanno inserite i template delle mail da inviare, con i relativi placeholder da rimpiazzare nel momento di personalizzazione della stessa. Il metodo ha come argomenti queste variabili: o SPWeb web; o Dictionary<String, EmailTemplate> emailTemplates: è l’insieme dei templates passati per la generazione della lista di configurazione; o KeyValueList.KeyValueListPermissions permissions: sono i permessi per la generazione della lista di configurazione; o Boolean forceToElevatedPrivileges Ed esegue questa funzione: 1. Viene creato un nuovo Dictionary<String, String> denominato keys; 2. Per ogni key dell’emailTemplates, vengono generate due key all’interno di keys con tale struttura: 7 http://msdn.microsoft.com/it-it/library/microsoft.sharepoint.administration.aspx 8 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.utilities.aspx 9 http://msdn.microsoft.com/it-it/library/system.web.ui.webcontrols.aspx
  • 43. 43 Key Value Key + “body” emailTemplates[key].body Key + “Subject” emailTemplates[key].subject 3. Viene invocato il metodo KeyValueList.CreateKeyValueList(web, EMAIL_TEMPLATE_LIST, keys, permissions, forceToElevatedPrivileges), per ottenere la lista di nostro interesse. La necessità di spezzare in due keys si basa sul fatto di poter usufruire dei metodi generati in precedenza, cosicché non si debba creare ulteriore codice già fornito da funzioni similari già scritte. 3.3.1.5.3 Void getEmail Questo è il metodo che va a pescare dalla lista generata in precedenza fornendo body e subject della mail da inviare, e sostituendo i placeholder con i valori reali da introdurre. Gli argomenti in ingresso sono: o SPWeb web; o String emailType: definisce il tipo di emailTemplate da pescare; o Dictionary<String, String> replaceTable: è la lista con cui vengono sostituiti i placeholder con i valori reali; o Out String body: è il valore del body che viene restituito in uscita; o Out String subject: è il valore del subject restituito in uscita È importante sottolineare un fatto: il replaceTable è un dictionary che, pur avendo una struttura implementabile a livello generico, si è scelto di consentire allo sviluppatore di averne piena libertà di creazione, lasciando questa senza un metodo di composizione appropriato. Poiché ogni implementazione del servizio mail è costumizzato in maniera specifica al progetto di interesse, vincolare la raccolta dei dati renderebbe praticamente bloccata la struttura di tutta la site collection, bloccando liste, dati, contenuti e particolarità che il cliente potrebbe andare a richiedere per la propria applicazione. Da un’analisi teorica, il dictionary andrebbe ricreato ogni volta, poiché sono sin troppe le variabili in gioco che potrebbero cambiare (numero di placeholder, ente invocante, ente
  • 44. 44 ricevente, variabili da inserire nei placeholder, per citarne alcuni), che non permettono di avere un oggetto (item di una lista) fisso da sfruttare. Nel caso di una lista, ipotizzando di avere n campi con m possibili valori teorici per ognuno di essi, avremmo un ordine di grandezza di nm, generando una mole di dati ingestibile all’aumentare di n ed m, oltretutto portando ad un vantaggio in termini di tempo a dir poco irrisorio: l’accesso alle liste è praticamente immediato, ed allo stesso modo recuperare i valori all’interno degli items selezionati. Una minima perdita in termini di tempo sopperisce appieno al risparmio in termini di spazio occupato che proporrebbe l’altro tipo di soluzione. Tornando a parlare del metodo, esso esegue queste operazioni: i. Nelle variabili body e subject in ingresso vengono posti dei valori di esempio; ii. Vengono recuperati, tramite il metodo della classe KeyValueList GetKeyValue i contenuti di body e subject di interesse per la mail; iii. Per ogni keyValuePair presente nel dictionary, viene verificata la possibile sostituzione del placeholder: se il value non è null, viene presa la sezione del placeholder (caratterizzata da “%”+ entry.key + “%”) e sostituita sia nel body che nel subject dal value effettivo, oppure, nel caso contrario, con uno spazio vuoto; Tutto il processo è interno ad un try / catch, che in caso di errore generico manda una segnalazione nel log di sistema. 3.3.1.5.4 Void Send Questo metodo consente l’effettiva generazione della mail e il conseguente invio della stessa tramite il metodo fornito dalle SPUtility SendEmail, senza avere degli allegati ad essa associata (per gli allegati, si rimanda al metodo successivo). Come signature, il metodo ha: o SPWeb web; o String to: è l’indirizzo mail del destinatario; o String tipoMail: è il tipo di mail template da recupare; o Dictionary<String, String> replaceTable; o String from: è l’indirizzo mail del mittente; o String emailCC: sono gli indirizzo mail degli utenti a cui la mail viene inoltrata in copia.
  • 45. 45 Il flusso è così descritto: Figura 18 - Flusso Send Come è possibile constatare, il metodo verifica la presenza dei campi nulli per i ruoli cardine dell’invio della mail (mittente), generando un’exception nel caso di valori mancanti. A completare, associato a questo stesso metodo ve ne è un altro in overload, con signature leggermente diversa: o Invece di avere una variabile to di tipo string, ne abbiamo una identica di tipo SPUser String messaggio; String oggetto getEmail(web, tipoMail, replaceTable, out oggetto, out messaggio) stringDictionary headers = new StringDictionary() headers.Add(“to”, to); From != null Errore Headers.Add(“from”, from) emailCC != null Headers.Add(“cc”, emailCC) FALSO FALSO VERO VERO Headers.Add(“subject”, soggetto) Headers.Add(“content-type”, “text/html”) SPUtility.SendEmail(web, headers, messaggio)
  • 46. 46 FALSO Urls != null Foreach(url) Tr y SPFile file = web.GetFile(url) Message.Attachments.Add(new Attachment(file.OpenBinaryStream(), file.Name) Errore VERO FALSO VERO EXCEPTION E Questo dunque andrà a recuperare la mail associata allo User passato e, se questa risulterà esistere, verrà inviata la mail invocando il metodo descritto sopra. 3.3.1.5.5 Void SendWithAttachments Quest’ultimo metodo della classe è decisamente più articolato dei precedenti, poiché l’implementazione dell’inserimento degli allegati richiede numerosi passaggi supplementari. Oltre agli argomenti descritti nel metodo Send, quest’ultimo ha una variabile supplementare: o String[] urls: il percorso dei file da allegare Il metodo, dopo aver definito le string messaggio e oggetto, crea un nuovo oggetto di tipo MailMessage, a cui vengono associati, se presenti, mittenti, destinatari e lettori in copia (con le stesse restrizioni presenti in Send). Dopo aver associato alle properties dell’oggetto MailMessagge i valori Property Value isBodyHtml True Body messaggio Subject oggetto Viene verificata la presenza di elementi nell’array urls Figura 19 - Flusso SendWithAttachments
  • 47. 47 In modo tale da consentire l’associazione al messaggio di tutti gli allegati effettivamente esistenti, senza generare problemi verso quelli funzionanti ed associabili. A questo punto, poiché non è possibile utilizzare il metodo SPUtility.SendEmail proposto in Send, dato che questo non gestisce propriamente gli allegati, c’è il bisogno di ricreare l’ambiente smtp per l’invio della mail: o Viene recuperato il Local.OutboundMailServiceInstance, che è l’istanza locale che definisce i settaggi per l’invio delle mail tramite smtp; o Se non esistente il serviceInstance descritto al punto precedente, viene settato come suo valore il web.Site.WebApplication.OutboundMailServiceInstance, così da avere quello stesso della site collection; in caso di assenza pure di questo si da errore e viene impedito l’invio; o A questo punto viene recuperato l’smtp server address tramite il serviceInstance.Server.Address, e generato un nuovo smtp client puntato a questo indirizzo; o Ora non resta che inviare il message tramite il comando client.Send(message) La necessità del controllo sul Local.OutboundMailServiceInstance è per ovviare al valore null che questo assume arbitrariamente, impedendo l’invio stesso della mail al metodo. Con il web.Site.WebApplication.OutboundMailServiceInstance i rischi di null exception si riducono al minimo, garantendo dunque il corretto funzionamento dell’smtp client.
  • 48. 48 3.3.1.6 PubManager La classe PubManager fornisce quei metodi che permettono la configurazione delle PublishingWeb10 e PublishingPage11 classes. PublishingWeb, come descritto nelle specifiche Microsoft, “provides publishing-specific behavior for an SPWeb that supports publishing, including access to child PublishingPage and PublishingWeb instances, variations support, navigation settings, PageLayout and Web template restrictions, and Welcome page settings. This class wraps an SPWeb instance that has the publishing feature activated”. In questo modo, nelle site collection in cui vi è implementata la feature di publishing al suo interno, viene permessa la definizione custom di tutte quelle pagine su cui potranno intervenire gli utenti finali tramite il front-end della site collection, configurando primariamente i permessi su PageLayout e sul Web Template, e gestendo gli accessi sulle Pagine di Publishing e sui Web di Publishing figlie di questa. PublishingPage invece, sempre dalla specifiche Microsoft, “contains references to the parts that define the .aspx page, such as the PageLayout class, the SPContentType class, resources, and other parts. It contains PublishingPage content as field values in the document library item”. In questo modo le possibili pagine di Publishing, oltre che ad ereditare dal PublishingWeb, può aver definite le proprie caratteristiche particolari usando le strutture base di SharePoint (in questo caso, Document Library) e venendo trattata come un qualsiasi altro item, e dunque con le stesse personalizzazioni. Anche in questo caso vi è la necessità di creare un oggetto che definisca un insieme di variabili, che verrà definito PageDefinition. Invece di creare una classe pubblica, si è optati di usare uno struct, visto che non abbiamo metodi costruttori ma unicamente variabili al suo interno. I metodi ritenuti utili alla causa invece sono sette, con, in alcuni casi, overload di questi. 3.3.1.6.1 Struct PageDefinition Lo struct ha 7 variabili private al suo interno, a cui vi si ha accesso tramite i metodi get / set ad esse associati:  String pageFileName: è l’url della PublishingPage da generare;  String pageTitle: è il titolo della PublishingPage; 10 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.publishingweb.aspx 11 http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.publishingpage.aspx
  • 49. 49  String controlPath: è l’url, se definito, dello user control associato alla pagina;  String pageLayout: è il nome della PageLayout associata alla PublishingPage;  Boolean includeInCurrentNavigation: indica se inserire o no nel site (o subsite) di pertinenza il suo link diretto;  Boolean includeInGlobalNavigation: indica se inserire o no nella site collection di pertinenza il suo link diretto;  String webPartZoneId: legato al controlPath, definisce in quale WebPartZone inserire lo user control definito in precedenza. 3.3.1.6.2 PublishingPage CreatePublishingPage Il primo metodo implementato è quello che operativamente crea la PublishingPage e lo inserisce all’interno della PublishingPageCollection passato in ref. Come argomenti abbiamo: o SPWeb web; o String pageNameUrl: è l’url della pagina da generare; o String pageTitle: è il titolo della pagina; o String pageLayoutName: è il nome del PageLayout da associare; o Ref PublishingWeb pubWeb: è la PublishingWeb da cui pescare, in caso di evenienza, la PublishingPageCollection; o Ref PublishingPageCollection pubPages: è l’insieme delle pagine a cui verrà aggiunta quella in fase di creazione. Il funzionamento è il seguente: i. Se pubWeb è vuoto, vengono associate ad esso le PublishingWeb di web tramite il metodo PublishingWeb.GetPublishingWeb(web); ii. Se pubPages è vuota, viene associata la collection di PublishingPages di pubWeb tramite il metodo pubWeb.GetPublishingPages(); iii. Viene creato un oggetto PageLayout recuperando dal web quello definito con il name pageLayoutName con il metodo GetPageLayout(web, pageLayoutName) (che verrà descritto a breve);
  • 50. 50 iv. Viene creato un riferimento PublishingPage chiamato pubPage a cui viene associato l’oggetto che viene creato all’interno di pubPages con il metodo pubPages.Add(pageNameUrl, pageLayout); v. Viene valorizzata la property Title di pubPage con il valore pageTitle, ed eseguito un update dell’oggetto stesso. Il valore restituito sarà la stessa PublishingPage generata. In caso di eccezioni, verrà generato un messaggio di Log con i riferimenti a ciò che a portato questo errore. Il metodo, oltretutto, effettua un overload in cui la signature manca degli argomenti webPub e webPages: il metodo setterà questi a null e invocherà il metodo appena descritto. 3.3.1.6.3 PageLayout GetPageLayout Questo metodo accessorio è utile nel CreatePublishingPage per recuperare il PageLayout associato alla stringa passata. Gli argomenti del metodo sono: o SPWeb web; o String pageLayoutName; Il metodo recupera il PublishingSite della site Collection, e l’associata PageLayoutCollection, va a prendere il relativeUrl in questione. Se la stringa ottenuta risulta uguale al solo “/”, stando ad indicare che ci si trova di fronte ad una site collection posta come primaria all’interno della Web Application, andremo ad attingere direttamente da “/_Catalogs/masterpages/<PageLayoutName>”; viceversa, nel caso ci trovassimo in una site collection più interna, avremmo come indirizzo di riferimento “<web.Site.RelativeUrl>/_catalogs/masterpages/<PageLayoutName>”. 3.3.1.6.4 List<PageDefinition> CreatePageDefinitionList Questo metodo di appoggio permette di creare, come definito dalla signature, la lista delle PageDefinition da dare in pasto alle altre funzioni prendendo i dati dalla matrice passata in input. Unica variabile di input è la matrice di String[,] pageDefinitionMatrix, che conterrà i valori, in ordine:
  • 51. 51  PageFileName;  PageTitle;  ControlPath;  PageLayout;  WebZonePartId;  IncludeInCurrentNavigation;  IncludeInGlobalNavigation; Per poter popolare l’oggetto PageDefinition in creazione. Il metodo analizzerà tale matrice, e per ogni riga, fino al raggiungimento dell’UpperBound, verrà generato un oggetto PageDefinition con i valori relativi, ed inserito all’interno di una lista, che sarà oltretutto l’output della funzione stessa. 3.3.1.6.5 List<PublishingPage> CreatePublishingPagesSetWelcome Questo metodo porta alla generazione della Lista delle publishing Pages. Come argomenti della signature abbiamo: o SPWeb web; o List<PageDefinition> pageDefinitions: è la lista con le PageDefinition da convertire in publishing Pages; o String welcomePageFileName: è il nome della pagina che diventerà quella di Welcome. La costruzione della lista di PublishingPages avviene sin dall’inizio, e viene seguita dalla configurazione della SPFile welcomePage, della PublishingWeb pubWeb e della PublishingPageCollection pubPages a null. Dunque, per ogni PageDefinition all’interno della lista, viene avviato un try / catch strutturato che permetterà di poter creare tutte le Publishing pages effettivamente funzionanti, senza dare un blocco nel caso di malfunzionamento di una di queste. Completato, si passa alla fase di associazione della welcomePage: nel caso il valore della stringa risultasse non nulla: i. Si rompe la navigazione sia per la CurrentIncludesPages che per la GlobalIncludePages; ii. Viene settata la pagina definita come pubWeb.DefaultPage;
  • 52. 52 iii. Viene eseguito un update del pubWeb; iv. Viene chiuso pubWeb Da evidenziare, oltretutto, che il metodo stesso ha un caso di overload così definito: o Invece della List<PageDefinition>, viene passata una matrice pageDefinitionMatrix: verrà invocato nuovamente il metodo, con List<PageDefinition> ricavata tramite il metodo CreatePageDefinitionList(pageDefinitionMatrix). Figura 20 - Flusso CreatePublishingPagesSetWelcome VERO FALSO VERO FALSO Try publishingPage pubPage = PubManager.CreatePublishingPage(…) pubPage.IncludeInCurrentNavigation pubPage.IncludeInGlobalNavigation pageFileName == welcomePageFileName welcomePage = pubPage.ListItem.File pubPage.checkOut() pageDefinition.ControlPath != null Inserimento WebPart pubPage.checkIn() pubPage.ListItem.File.Approve(String.Empty) pubPage.ListItem.File.Publish(String.Empty) pages.Add(pubPage) Log Error EXCEPTION E
  • 53. 53 3.3.1.6.6 List<PublishingPage> CreatePublishingPages Il metodo proposto è una semplice modifica del metodo descritto al punto precedente: oltre la matrice ed all’SPWeb, non verrà passato altra variabile. Il return invocherà il metodo CreatePublishingPagesSetWelcome(web, CreatePageDefinitionList(pageDefinitionMatrix), String.Empty). In tale modo non verrà configurata la pagina di Welcome, e verranno conservate le definizioni di pubWeb.CurrentIncludePages e pubWeb.GlobalIncludePages. 3.3.1.6.7 Void DeletePublishingPagesSetWelcome Al contrario dei precedenti, questo metodo va a rimuovere le Publishing Pages presenti all’interno della lista di PageDefinition in input, e va nuovamente a configurare la Welcome Page. I parametri di input sono similari ai precedenti metodi: o SPWeb web; o List<PageDefinition> pageDefinitions; o String welcomePageFileName. In questa circostanza, viene: i. Recuperato il pubWeb da web; ii. Recuperato il pubPages da pubWeb; iii. Creato il percorso per associare la nuova WelcomePage, nel caso in cui welcomePageFileName non fosse nulla; iv. Per ogni pegeDefinition in pageDefinitions, viene rimosso l’item presente in pubPages associato al pageFileName tramite un try / catch; v. Chiuso il pubWeb. Da notare il “barbaro” utilizzo del try / catch al punto iv. Il catch vuoto, contrario ad ogni tipo di programmazione pulita e funzionale, è dovuto al fatto che SharePoint, nella versione 2007, non ha avuto un metodo che eseguisse il tentativo di ricerca dell’oggetto, senza andare in errore se questo non fosse esistente. In tal maniera, oltre ad avere un controllo sull’effettiva
  • 54. 54 esistenza dell’oggetto, permettiamo anche una retrocompatibilità del metodo con la versione 2007 della piattaforma. A chiudere la trattazione su questo metodo, è bene far notare, in maniera similare al caso di CreatePublishingPagesSetWelcome, esiste un metodo in overload per questo stesso, con variabili di ingresso variate (invece che List<PageDefinition> la matrice pageDefinitionMatrix), ma stesso comportamento, con return invocante il metodo. 3.3.1.6.8 Void DeletePublishingPages In maniera similare al CreatePublishingPages, riceve come input la matrice PageDefinitionMatrix, setta come String.Empty la WelcomePage e richiama il metodo DeletePublishinPagesSetWelcome con argomenti web, pageDefinitionMatrix, String.Empty.
  • 55. 55 3.3.2 Classi accessorie All’interno della feature descritta, sono state anche introdotte delle classi di supporto che si sono rese necessarie per un corretto e completo funzionamento di quelle descritte precedentemente. Due sono i blocchi cruciali da analizzare: i metodi forniti per il logging e quelli per la gestione delle security di SharePoint. 3.3.2.1.1 Logging La sezione di logging riveste un ruolo molto importante, in modo particolare nelle situazione di errore del prodotto: quest’ultima ci permette difatti di verificare, tramite un report puntuale, cos’è che ha causato l’eccezione. Potrebbe sembrare una funzione poco funzionale alle specifiche proposte, ma è utile, se non fondamentale, per lo sviluppatore in caso di problemi riscontrati durante il funzionamento della solution. È importante sottolineare, se non troppo evidenziato prima, che praticamente ogni metodo di quelli descritti nelle classi in precedenza usufruiscono di quelli descritti in questa sezione, proprio per i motivi citati sopra. Questa parte di feature è stata spezzata in due classi: quella di Logger, con la creazione della lista di log, i relativi costruttori e i metodi associati, e la LogExceptions, con i metodi che invocano i precedenti per una commistione corretta a seconda degli stati in cui ci si trova. L’elenco di metodi e classi, ora, sarà unificato, elencando prima quelli di Logger.cs, dunque quelli di LogExceptions.cs. 3.3.2.1.1.1 Class Logger La classe ha 4 variabili private:  SPWeb web;  SPListItem spFeatureLogItem;  SPFile spLogFile;  String logName.
  • 56. 56 Sono tutte a null in origine, e poi verranno popolati, a seconda del caso, tramite i costruttori di classe: 1. Logger (SPWeb destinationWeb, string feature) In questa prima situazione viene invocato unicamente il metodo Inizialize con i due input come suoi argomenti di ingresso (Inizialize verrà descritto a breve) 2. Logger (SPWeb destinationWeb, String feature, String logName) Questo secondo costruttore, invece, setta la variabile privata logName con il parametro di ingresso, per poi operare come quello precedente. Comprende inoltre un insieme di metodi atti a creare la lista di log, scrivervi al suo interno e gestirne gli item al suo interno. 3.3.2.1.1.1.1 SPList CreateLogListIfNotExists È il metodo di creazione della lista di log nella site collection SharePoint di nostro interesse. È un metodo privato. Senza argomenti in ingresso, pesca dalla variabili globali l’SPWeb, e si collega alla Lista di log. Se questa non venisse trovata, viene creata una nuova GUID riferita alla nuova lista generata, e modificata la colonna “title” chiamandola con la costante TITLE_LOG_LIST. Tutta il metodo sarà poggiato su due try/catch intrecciati tra loro: nel caso di malfunzionamento di entrambe le sezioni, verrà ritornato un valore null. 3.3.2.1.1.1.2 Void OpenLog È il metodo, privato, che verifica l’esistenza di un item nella lista di log e, se non esistente, crea un nuovo item, predisponendolo ad una successiva compilazione. Ha come argomenti in ingresso:  String feature: è il nome da attribuire al log item;  SPList spLogList: è la lista di log Il metodo opera secondo questo diagramma di flusso semplificato:
  • 57. 57 Figura 21 - Flusso OpenLog Il tutto viene eseguito con metodi già forniti dalle libraries a disposizione, tranne il metodo AddAttachmentToSPItem(), appartenente a questa stessa classe, che definiremo in seguito. 3.3.2.1.1.1.3 Void AddAttachmentToSPItem A completamento del metodo precedente, questo va ad associare gli attachments dell’item in maniera corretta, ripulendoli e portandoli ad un valore inferiore del MAX_LENGTH definito all’interno della classe. Anch’esso è privato e non ha variabili di input. Opera nella maniera seguente:  Setta a true gli UnsafeUpdates; Exists = false Controllati tutti gli item Esiste Exists = true spFeatureLog = listItem Exists Crea spFeatureLog logName != null url dei possibili attachments Attachments logFile.length > MAX_LENGTH spLogItem.Attachments.DeleteNow(logName) AddAttachmentToItem() VERO VERO VERO VERO FALSO FALSO FALSO FALSO FALSO VERO
  • 58. 58  Recupera la Collection di Attachments associata all’item;  Verifica la presenza del logName: in caso affermativo crea una stringa defLogName con quel valore  In caso contrario, definisce defLogName con valore la data formattata;  Viene aggiunto un Attachment con i parametri di pertinenza;  Viene recuperato l’SPFile associato al log e settato come spLogFile;  Setta a false gli UnsafeUpdates 3.3.2.1.1.1.4 Void Initialize È il metodo invocato dal costruttore, creando l’ambiente adatto alla verifica ed alla generazione della log list all’interno della site collection selezionata. Ha due argomenti in input:  SPWeb web;  String feature. Ed opera in maniera molto semplice: 1. Viene recuperata la stringa dell’url del web passato; 2. Vi si accede in modalità elevated privileges, creando un nuovo site; 3. Vengono settati all’interno di quest’ultima i permessi per gli UnsafeUpdates; 4. Viene invocato il metodo CreateIfNotExists() 5. Viene dunque verificata l’effettiva presenza (o creazione) della lista: in caso affermativo, viene avviato OpenLog(feature, spLogList), così da essere predisposti alla compilazione di un item; 6. Viene dunque revocato il permesso agli UnsafeUpdates L’utente sarà così abilitato alla compilazione dell’item di pertinenza per quella exception o informazione che risulterà necessaria in fasi successive di analisi prestazionali. 3.3.2.1.1.1.5 String LogLine È un metodo privato, che ritorna il contenuto da passare agli item nel campo di descrizione. Suddivide in tre possibili tipi di notifiche: ERROR, WARNING, INFO, definendo una variabile pubblica enum nella classe stessa.
  • 59. 59 La stringa di ritorno sarà così strutturata: <DateTimeAttuale> + <TipoNotifica> + <Messaggio Personalizzato>. 3.3.2.1.1.1.6 Void Write È il metodo che va a popolare l’SPFile associato al log. Ha come argomenti di ingresso:  LOG_TYPE type: è il tipo di log che verrà generato;  String message; Dopo aver dato i permessi agli UnsafeUpdates, viene aperto uno stream sull’spLogFile esistente, dunque uno StreamWriter su quest’ultimo. Dunque viene identificato il punto in cui iniziare a scrivere (tramite il metodo Seek), e scritta la riga di interesse tramite il LogLine. Dopo aver ripulito sia lo StreamWriter che lo Stream tramite il relativo metodo flush (svuotando il buffer associato a questi), e salvando il BinaryStream nell’SPFile, viene completata l’operazione. 3.3.2.1.1.1.7 Int AttachmentsLogComparator È un metodo accessorio utile per il clearAttacchments (che descriveremo subito dopo), in cui viene eseguita la comparazione temporale tra due SPFile, e la loro data di ultima modifica. Presi A e B due SPFile, verrà ritornato:  -1 se A.TimeLastModified < B.TimeLastModified;  0 se A.TimeLastModified = B.TimeLastModified  1 altrimenti 3.3.2.1.1.1.8 Void ClearAttachments Questo metodo verifica e rimuove gli attachments in eccesso, rimuovendo quelli che risulteranno i più vecchi. Il metodo ha una unica variabile di ingresso: l’int maxNumAttachments, che determina, come dice il nome stesso, il numero massimo di di Attacchments associati al log. Recuperati gli attachments associati all’item di interesse, verifichiamo se il numero di questi superino il numero massimo imposto di attachments. Se superiore, vengono recuperati tutti gli item, riferiti all’interno di una Lista di appoggio spFileList.
  • 60. 60 Su spFileList viene eseguito un sorting che ha come metodo di comparazione l’attchmentsLogComparator definito poco sopra, e, completato questo, vengono eliminati quelli che sono i valori più vecchi nella lista, invocando il delete(). Importante sottolineare che il metodo Delete() non rimuove il riferimento nella lista, ma propriamente l’SPFile associato, in modo tale da rimuoverlo pure all’interno degli Attachments dell’spFeatureLogItem. 3.3.2.1.1.1.9 void Close Senza argomenti nella signature, fa il Dispose del web utilizzato, rilasciando tutte le risorse non utilizzate. 3.3.2.1.1.2 Class LogExceptions Questa seconda classe della sezione poggia direttamente su Logger, invocandone sistematicamente metodi e costruttori per poter gestire in maniera ordinata e vincolata tutte le funzioni garantite. Esistono due metodi fondamentali, il LogMessage ed il ManageException, che strutturano, in maniera differente, il logger a disposizione, supportati da alcuni metodi accessori. 3.3.2.1.1.2.1 Void Alert Metodo di generazione di alert, che vada a visualizzare un messaggio predefinito, sotto forma di popup, nella pagina in cui si è verificato l’errore. 3.3.2.1.1.2.2 Void LogMessage In questo metodo viene generato un nuovo Attachment legato al log. Come parametri di ingresso abbiamo:  SPWeb web;  String message: il messaggio da salvare;  String featureName: è il nome della feature che ha generato il log;  Int maxAttachments: il numero massimo di attachments che può avere il log associato;  Logger.LOG_TYPE level: è il tipo di log da generare Il metodo si limita ad invocarne altri: 1. Inizialmente invoca il costruttore di Logger, con i parametri necessari
  • 61. 61 2. Creato l’oggetto log, ne invoca i metodi Write, ClearAttachments e Close in sequenza Effettua anche l’overload, senza la variabile LOG_TYPE: in questo modo, viene pre-impostato che il log si di error. 3.3.2.1.1.2.3 Void ManageException Strutturato in maniera similare al LogMessage, si differenza del precedente inserisce due righe di log all’interno dell’attachment, una che descrive classe e funzione che hanno generatore l’eccezione, e la seconda l’eccezione stessa. Come parametri aggiuntivi, rispetto a LogMessage, difatti ha due stringhe className e functionName, inserite direttamente dal metodo invocante per descriverne l’origine. 3.3.2.1.1.2.4 Void ManageExceptionGenericAlert Quest’ultimo metodo di classe invoca i precedenti ManageException e Alert, per fornire sia un messaggio nel log che un pop up in uscita. 3.3.2.1.2 Security La sezione di Security permette una gestione maggiormente efficace dei permessi forniti per l’utente all’interno della piattaforma SharePoint, fornendo dei metodi di assegnazione e di rimozione di tali nella site collection. Le security all’interno di SharePoint hanno una profonda importanza per tutta l’ambiente, poiché sono definibili ed impostabili a qualsiasi livello, dalla web application, scendendo per la site collection, le pages, le liste e le document Libraries, fino ad arrivare al singolo item, consentendo un accesso e diritti di creazione, editing, rimozione e visualizzazione in ogni più minimo particolare. Introducendo brevemente le funzionalità dei permessi, come già visto nella creazione di gruppi utenti, questi possono essere attribuiti a singoli utenti (pescati dall’Active Directory se attivata unicamente la Windows Authentication, oppure tramite oAuth o una claim-based authentication, oppure ancora direttamente da un database di credenziali personalizzato), a zero o più gruppi (popolati con le utenze), ed essere di tipo diverso, a seconda delle autorizzazioni che si vogliono concedere.
  • 62. 62 L’ambiente12 propone di default cinque livelli per i team sites (quelli che sono solitamente i template più utilizzati in ambito aziendale per la produzione di site collections) e innumerevoli permessi specifici da poter configurare. Per essere chiari, nella prossima parte della trattazione definiremo Securable tutti quegli elementi di SharePoint cui è possibile applicare dei criteri di visibilità puntuale, che essi siano item, list, document library, e via dicendo. Dunque, nel caso dei livelli, si passa da:  Limited Access, in cui l’utente / gruppo ha unicamente diritto di accesso alle risorse condivise (è un particolare livello, perché si tende ad utilizzarlo per sgranarne meglio i permessi della stessa utenza in casi più specifici, definendo caso per caso, Securable per Securable, il tipo di autorizzazione concessa);  Read, in cui l’utenza può leggere i contenuti del Securable autorizzato;  Contribute, in cui è possibile, oltre alle autorizzazioni precedenti, creare items all’interno di Lists e Document Library  Design, in cui l’utenza, assieme ai permessi del Contribute, può modificare le pages e approvare gli items generati da altre utenze;  Full Control, in cui l’utente / gruppo può compiere qualsiasi operazione sul Securable preso in considerazione. Questi livelli permettono di avere una sgranatura abbastanza ampia degli user all’interno della web application presa in considerazione, ma nel caso avessimo bisogno di una più approfondita suddivisione dei ruoli, vi è la possibilità di configurare, uno ad uno, tutti i permessi concessi e distinti, personalizzati per ogni tipo di Securable disponibile. Altro tema toccato all’interno di questa sezione, è la protezione di contenuti sensibili privati, come ad esempio password all’interno di liste di configurazione. Non è sufficiente togliere i permessi di view sull’item stesso, perché nel caso di utilizzo di questa per determinate funzionalità, non risulterebbe utilizzabile. Dunque si può preferire l’inserimento di un sistema di codifica e decodifica di questi contenuti, con due metodi ad hoc. 12 http://technet.microsoft.com/it-it/library/cc721640(v=office.14).aspx per maggiori approfondimenti sul tema dei permessi in ambiente Sharepoint 2010
  • 63. 63 Andiamo ora in descrizione delle due classi sviluppate, una chiamata Permissions, l’altra EncodeDecode, in modo da vederne le funzionalità implementate. 3.3.2.1.2.1 Class Permissions Vi sono 4 metodi (in overload) per la gestione degli Assignments, mentre 2 per la rimozione di tutti i permessi. 3.3.2.1.2.1.1 Bool Assign Metodo che permette l’assegnazione dei permessi rispetto un item od una lista rispetto ad una determinata utenza, o gruppo. Restiuisce true nel caso siano assegnati i permessi direttamente al Securable indicato, false in caso contrario. Ha 4 overload, con unico argomento comune l’SPPrincipal, che è la property che users, groups e ad Users hanno condivisa, mentre si differenziano per il tipo di Securable da autorizzare (SPList o SPListItem), e dalla modalità in cui viene definito il permesso (SPRoleType o SPRoleTypeDefinition). Al posto di Securable può essere inserito a scelta un item o una list (la stessa document library può essere trattata, in questa situazione, come tale), cosicché tutti gli overload siano descritti in maniera completa. La struttura generica del metodo è così descrivibile:
  • 64. 64 Figura 22 - Flusso Assign 3.3.2.1.2.1.2 Void DeleteAll In maniera similare al precedente, vi sono 2 metodi in overload, uno per gli items, uno per le liste, che vanno a dissociare i permessi già impostati. Avendo come parametro di ingresso, a seconda del caso, SPList oppure SPListItem, invoca il metodo BreakRoleInheritance(false), che va a eliminare l’ereditarietà dal padre del Securable e, tramite il boolean false, rimuove pure quelli che erano fino a prima i permessi associati. 3.3.2.1.2.2 Class EncodeDecode Questa seconda classe di security, come già descritto in precedenza, agisce sull’encoding e decoding di stringhe, fornendo rispettivamente un metodo per i due casi. SPRoleAssignment = new SPRoleAssignment(spPrincipal) SPRoleType SPRoleDefinition = […].RoleDefinition.GetByType(spRoleType) SPRoleAssignment.RoleDefinitionBindings.Add(SProleDef) Permessi specifici per il Securable Securable.RoleAssigments.Add(SpRoleAssignment) Return true Return false VERO VERO FALSO FALSO
  • 65. 65 La classe importa il namespace System.Security.Criptography13, che permette propriamente la gestione di codifica e decodifica dei dati in maniera protetta all’interno della site collection associata. I metodi indicati si rifanno all’algoritmo di Rijndael, che è la specifica di implementazione dell’AES, Advanced Encryption Standard, usato come algoritmo standard dal governo degli Stati Uniti, e di cui faremo un approfondimento in appendice. Costante privata nella classe, e di rilevante importanza, è IV, stringa di inizializzazione del vettore di codifica dell’algoritmo. 3.3.2.1.2.2.1 String Encode Il metodo di encoding, poiché basato su di un metodo di cifratura a blocchi, necessita della definizione della dimensione del blocco da utilizzare durante la crittografia, e della dimensione della chiave da usare. Per essere aderente allo standard AES, vengono imposte entrambe le dimensioni a 128 bit. Parametri di ingresso sono:  String S: è la stringa da convertire;  String key: è la chiave da usare per la crittazione. Il tutto si basa sulla creazione di un oggetto RijndaelManaged chiamato rjm, in cui vengono definiti le properties: Property Value KeySize 128 BlockSize 128 Key ASCIIDecoding.ASCII.GetBytes(key) IV ASCIIDecoding.ASCII.GetBytes(IV) Dunque viene generata lo stream di input, convertendo in formato UTF-8 la stringa in ingresso, salvandola dunque all’interno di un byte[]. Ora avviene l’encoding vero e proprio: rjm invoca il createEncryptor, e passa lo stream di input per convertirlo in un nuovo array di byte di output. 13 http://msdn.microsoft.com/it-it/library/system.security.cryptography(v=vs.80).aspx
  • 66. 66 A chiusura, l’output viene convertito dall’array in una stringa Base64, così da avere il return di interesse. 3.3.2.1.2.2.2 String Decode In maniera similare a ciò che è stato definito in precedenza, questo metodo esegue il decoding di una stringa generata da Encode. Ha le stesse variabili di ingresso, necessita di un RijndaelManaged con uguali properties, variano solo le attività da svolgere sulla stringa di input:  Converte la stringa da Base64 in un array di byte;  Rjm invoca il metodo di Decoding, restituendo un nuovo array di byte;  Quest’ultimo viene convertito in una stringa in formato UTF-8, così da avere il valore effettivo dell’encription.
  • 67. 67 3.4 Feature BlockUsers La seconda feature della solution ha importanza per la gestione delle fasi di manutenzione della site collection su cui questa viene attivata. Ci garantisce difatti il blocco degli accessi a tutte le pagine della site collection quando non si risultasse appartenenti al gruppo degli amministratori di tale. Al suo interno viene importato il modulo BlockedUsers, che di conseguenza va a pescare l’ascx BlockUsers.ascx a disposizione nella solution. È importante analizzare il funzionamento dell’xml di BlockedUser e di BlockUsers.ascx.cs per capire il funzionamento di tale feature. 3.4.1 BlockedUsers/Elements.xml Il codice di questo file è molto ridotto, ma compie il ruolo fondamentale di delega di un controllo alla source di interesse. Difatti, tramite Setta il controllo di delega degli accessi a tutte le pagine (tramite l’associazione dell’id GlobalNavigation) alla source ascx BlockUsers, che avrà i suoi metodi di controllo per verificare l’utenza che ne richiede l’accesso. Utile constatare che tale ascx viene caricato in automatico al deploy della solution nella piattaforma, ma risulterebbe inutilizzabile ed inutile, se non nel caso di associazione come “filtro” per le utenze aventi diritto di modifica nel momento di manutenzione della site collection.
  • 68. 68 3.4.2 BlockUsers La funzione dell’ascx in questione è molto limitato, ma risulta efficace nel caso in cui abbiamo descritto all’inizio della sezione. È tutto concentrato all’interno del PageLoad associato: Figura 23 - Flusso BlockUsers
  • 69. 69 4 Implementazione del framework Questa terza sezione del documento va a trattare una possibile implementazione del nostro prodotto all’interno di un effettivo sistema informativo. Ciò è utile per dimostrare come il framework possa essere posto a base di un progetto generico per fornire supporto allo sviluppatore, sia a livello logico che a livello di programmazione. Andremo dunque ad analizzare un prodotto conseguente del framework in modo da mostrare come questo possa essere usato, procedendo con una descrizione dei requisiti e delle specifiche di progetto, per poi approfondirne una porzione del flusso per mostrare i vari frammenti più interessanti. Si evidenzia il fatto che questa parte di trattazione prenderà solo poche delle funzioni andatesi ad implementare nel capitolo precedente, poiché non tutti i metodi sono stati utilizzati all’interno dell’esempio in questione. 4.1 Esempio di progetto 4.1.1 Scopo La struttura dell’ufficio analizzato è “owner” del processo di gestione delle convenzioni. Tale processo è suddiviso in una serie di fasi consecutive ma che prevedono alcuni ricicli interni per approvazione e/o raccolta documentazione aggiuntiva. La forte necessità di avere un’applicazione a governo di tale processo è giustificata dalla necessità di mantenere il raccordo ed il coordinamento delle richieste che provengono dall’esterno e sono traversali. Il sistema si deve fare carico di raccogliere tutte le informazioni in ogni fase del processo e di consentire un’agile gestione di queste. Oltre a gestire lo storico del processo nel tempo. 4.1.2 Ruoli nel sistema Nel processo sono coinvolti attori con diversi ruoli. Ogni attore accede all’applicazione per la consultazione dello stato dei processi di propria competenza, ed eventualmente ne legge il dettaglio, esegue operazioni ed inserisce nuova informazioni.