mercoledì 30 dicembre 2009
Blogs su SharePoint
http://nonsolosharepoint.wordpress.com/
http://sharepointpig.wordpress.com/
domenica 27 dicembre 2009
SharePoint 2007 e le risorse globali
Siccome con WSPBuilder non è possibile ottenere un manifest così fatto è necessario procedere a mano, ma facendoci aiutare da WSPBuilder fin dove possibile.
Per prima cosa copiare nella root del progetto il file WSPBuilder.exe.config e impostare a true la proprietà BuildDDF:
Mettere i file di risorse nella cartella Resources all'interno della cartella 12.
1 - Generare una wsp, copiarla e rinominarla con estensione .cab.
2 - Aprire il file cab ed estrarre il manifest.xml.
3 - Modificare il file cab aggiungendo sotto
<rootfiles> <rootfile location="Resources\myResource.en-US.resx"> <rootfile location="Resources\myResource.resx"> </rootfile>
il codice seguente
<applicationresourcefiles> <applicationresourcefile location="myResource.en-US.resx"> <applicationresourcefile location="myResource.resx"> </applicationresourcefile>
4 - Scaricare il "Microsoft Cabinet Software Development Kit" e creare il file CAB a mano con MakeCab.exe.
5 - Rinominare il file cab in wsp e installarla in sharepoint con stsadm.
Dopo aver fatto tutto questo, però, mi sono accorto che i file di risorse invece di essere compiati nella cartella App_GlobalResources, vengono copiati in un cartella "resources" sempre all'interno della web application di SharePoint ospistata da IIS nella quale la nostra wsp è stata deployata.
Dopo un po' di ricerche ho trovato questo articolo (http://www.mikhaildikov.com/2007/03/sharepoint-resources-types-use-and_2163.html) in un blog che spiega bene come in effetti gli elementi de manifest ApplicationResourceFiles e Resources siano inutili e suggerisce un modo per copiare a runtime i file di risorse nella cartella App_GlobalResources. Un altro utile articolo sui file di risorse è "SharePoint Internals: Resources".
Se qualcuno ha sperimentato altri modi ho ha trovato il sistema di usare i sopra citati elementi del manifest non abbia problemi a scrivere un commento. La stessa cosa vale se sapete come funziona il meccanismo delle risorse in SP 2010. Nella speranza che ci siano stati dei miglioramenti nella gestione delle risorse globali.
mercoledì 23 dicembre 2009
SharePoint 2010 Client Object Model
Vi segnalo due video in cui parla Andrew Connell:
Overview of the Client Object Model
ECMAScript Client Object Model
Nell'articolo seguente invece viene fatto un paragone tra le applicazioni client stile SP 2007 e quelle che saranno con SP 2010:
SharePoint 2010: Introducing the Client Object Model
Nel secondo in particolare, fate attenzione quando viene mostrato il controllo SharePoint:ScriptLink che ha un attributo nuovo LoadAfterUI. Questo attributo non viene spiegato ma immagini serva per indicare a SharePoint di caricare lo script sp.js in modo asincrono, dopo che la pagina è stata caricata completamente.
Il client object model faciliterà l'accesso ai dati. Esistono ancora i web service, ma il client object model ne è una valida alternativa.
Altra novità sono le REST API di SharePoint.
giovedì 10 dicembre 2009
Costruire un sito web - riflessioni
Bisogna avere un progetto, segliere i materiali e seguire gli standard. Gli architetti che disegnano la casa hanno anche le basi di ingegneria per sapere che quello che disegnano starà in piedi, poi si fanno aiutare per i calcoli delle forze, ma un'idea di base riescono a farsela da soli; almeno i più bravi. I problemi da affrontare nel progettare una casa sono sempre gli stessi, al massimo aumentano un po' le complessità se la casa è a più piani, in una zona sismica oppure un grattacielo. Di certo i materiali sono pressapoco sempre gli stessi: cemento, legno, ferro etc. Gli architetti più smalizziati e ripesttosi delle leggi si preoccupano dell'abbattimento delle barriere architettoniche e per endere più confortevole e abitabile la casa pensano a una serie di servizi utili a chi ci abiterà.
Se ci pensate progettare un sito web ha le stesse analogie, purtroppo la sua costruzione non sempre segue le stesse regole utilizzate per progettare una casa. Spesso i designer non parlano le lingue del web, ragionano solo con la carta e curano solo l'aspetto finale del sito. Usabilità (i confort della casa) o l'accessibilità (l'abbattimento delle barriere architettoniche) sono parole usate a puro titolo commerciale, ma non ne conoscono le basi. La stessa cosa spesso la si può dire anche per gli stessi sviluppatori. Conosco programmatori ASP.NET che non conoscono il protocollo HTTP, che non sanno come funzionano le FORM. Altri che ignorano il linguaggio CSS e non sanno che per scrivere uno script Javascript cross-browser è meglio affidarsi al DOM del W3C, usano ancora "document.all"! Come se un muratore non sapesse fare il cemento o riconoscere un mattone.
Ho parlato con grafici che non conoscevano le unità di misura del web, lavoravano solo in pixel. Altri che non conoscevano il significato delle misure in percentuale: "allora a 1024x768 la colonna destra la facciamo del 30%, mentre a 800x600 la facciamo del 25%"! Cosa? Fissiamo una percentuale e la teniamo per tutte le risoluzioni.
Nessuno di noi si cimenterebbe da solo a costruirsi la casa, mentre tutti bene o male abbiamo provato a fare un sito. Chi lo fa di professione dovrebbe approfondire i fondamentali e specializzarsi nel proprio ruolo, ma sempre più spesso questo non si fa.
sabato 5 dicembre 2009
Un po' di medicina per i nostri CSS
Vi riporto un po' di link utili menzionati nel libro di siti in cui vengono presentati i vari bug che affliggono i più comuni browser.
- Browser Bugs presso CSS-Discuss (http://css-discuss.incutio.com/?page=BrowserBugs)
- Position is everything (http://www.positioniseverything.net/) Modern browser bug explained in detail.
- WordPressb CSS Codex - Fixing Browser Bugs (http://codex.wordpress.org/CSS_Fixing_Browser_Bugs)
giovedì 26 novembre 2009
Fatti non foste a viver come bruti ma per seguir virtute e canoscenza
Il libro in questione è "Progettare siti Web Standard" di Jeffrey Zeldman. Per chi non lo sapesse Zeldman e il fondatore di "Web Standars Project" (che ha vinto la "battaglia" della standardizzazione delle tecnologie usate dai browser) e di "A List Apart".
Buona lettura.
The Winner Is... 2
Il sito "Atm ha ricevuto un altro riconoscimento: “Miglior prodotto digitale” nella categoria “eGovernment and Istitutions” del concorso eContent Award Italy, patrocinato dalla Presidenza del Consiglio dei Ministri".
Boom Atm su internet: 35mila visite al giorno
ATM, CONSEGNATO IERI PREMIO ECONTENT AWARD ITALY PER SITO
giovedì 19 novembre 2009
Branding SharePoint 2010
Dello stesso autore una serie di articoli sul suo Blog che parlano del Branding di SharePoint 2010. Eccovi il link al primo post.
Ho anche trovato la versione aggiornata dello Sharepoint Manager (SPManager 2010).
martedì 10 novembre 2009
Dai diamanti non nasce niente dal letame nascono i fior...
Dimenticavo, devo ancora finire la guida di ARF!
A presto.
venerdì 30 ottobre 2009
Sono stato messo "AlFresco"
Mi raccomando, tornate a visitarmi e "portatemi le arance"!
martedì 27 ottobre 2009
SharePoint Future
Ultima considerazione, probabilmente con la nuova versione di SharePoint ARF andrà in pensione...
ARF Guide 0.9 è online
Potete scaricarla da Codeplex.
domenica 25 ottobre 2009
Guida ad ARF - in arrivo una nuova versione
lunedì 19 ottobre 2009
ARF Form Base Authentication and WSS Publishing
Nella wsp che si scarica dal sito ufficiale di ARF c'è un probolema con la feature ARF-FormsAuth, mancano le due cartelle contenenti gli schema delle liste custom. Siccome esiste una seconda feature che installa un'istanxa di queste liste e che non funziona se la prima feature non è attivata in modo corretto è necessario correggere l'errore di installazione. Per fare ciò è necessario rinominare la wsp di ARF in un file .cab, estrarre il contenuto e copiare le cartelle FormsMemberList e FormsRoleConfig contenute nella cartella della feature ARF-FormsAuth nella rispettiva cartella che si trova in 12\TEMPLATE\FEATURES. Fatto ciò è necessario riattivare la feature con stsadm -o activatefeature (usare l'opzione -force) e infine lanciare un IISRESET. Dopo questi passaggi sarà possibile attivare anche la feature ARF-FormsAuthLists.
La seconda feature, attivabile a livello di sito (SPWeb), dovrebbe consentire di creare delle pagine custom in WSS a partire dal template di pagina Basic.aspx, che al suo interno usa un campo (field) RichTextField, compreso nella soluzione ARF. Il condizionale è d'obbligo perchè non sono ancora riuscito a far funzionare la caratteristica. Di certo devo segnalare un errore: nella pagina Basic.aspx si fa riferimento alla master page /_catalogs/masterpage/spworks.master di cui non vi è traccia nella soluzione; pertanto la pagina risulta inutilizzabile. Per risolvere il problema consiglio di modificare la pagina utilizzando una più standard ~masterurl/default.master o ~masterurl/custom.master master page.
L'impressione al momento è che queste funzionalità siano solo una bozza e non effettivamente funzionanti, ma vi saprò dire una volta che le avrò provato davvero.
Come sempre rinnovo l'invito a collaborare con me se avete già avuto modo di fare esperianza con qualcuna delle funzionalità di ARF, in modo da avere una più ricca collezione di esperienze e di impressioni.
venerdì 16 ottobre 2009
Custom Master Page
Per un progetto ho creato una site definition graficamente molto gradevole ma del tutto inadatta ad ospitare le pagine delle liste (list form page), quindi ho dovuto trovare un sistema per poter applicare la mia master page alle sole pagine aspx presentate al visitatore, lasciando la default master page associata al resto delle pagine. Siccome le pagine associate alle liste usano la ~/_layouts/default.master, non posso associare la mia master page alla default.
A questo punto entra in gioco la custom master page, ovvero nella mia site definition, nel file ONET.XML, ho usato configuration id="1" name="Blank" custommasterurl="/_catalogs/masterpage/clinicalmaster/ClinicalBasic.master", mentre nel codice SPweb.CustomMasterUrl e nelle pagine aspx ~masterurl/custom.master.
In questo modo tutte le pagine originali di WSS continuano a lavorare come prima.
mercoledì 14 ottobre 2009
Rilasciata nuova versione della guida su ARF
venerdì 9 ottobre 2009
ServerTemplate - Identificativi dei tipi di lista
100 | Generic list (00BFEA71-DE22-43B2-A848-C05709900100) |
101 | Document library (00BFEA71-E717-4E80-AA17-D0C71B360101) |
102 | Survey (00BFEA71-EB8A-40B1-80C7-506BE7590102) |
103 | Links list (00BFEA71-2062-426C-90BF-714C59600103) |
104 | Announcements list (00BFEA71-D1CE-42de-9C63-A44004CE0104) |
105 | Contacts list (00BFEA71-7E6D-4186-9BA8-C047AC750105) |
106 | Events list (00BFEA71-EC85-4903-972D-EBE475780106) |
107 | Tasks list (00BFEA71-A83E-497E-9BA0-7A5C597D0107) |
108 | Discussion board (00BFEA71-6A49-43FA-B535-D15C05500108) |
109 | Picture library (00BFEA71-52D4-45B3-B544-B1C71B620109) |
110 | Data sources |
111 | Site template gallery |
112 | User Information list |
113 | Web Part gallery |
114 | List template gallery |
115 | XML Form library |
116 | Master pages gallery |
117 | No-Code Workflows |
118 | Custom Workflow Process |
119 | Wiki Page library |
120 | Custom grid for a list (00BFEA71-3A1D-41D3-A0EE-651D11570120) |
130 | Data Connection library |
140 | Workflow History |
150 | Gantt Tasks list (00BFEA71-513D-4CA0-96C2-6A47775C0119) |
200 | Meeting Series list |
201 | Meeting Agenda list |
202 | Meeting Attendees list |
204 | Meeting Decisions list |
207 | Meeting Objectives list |
210 | Meeting text box |
211 | Meeting Things To Bring list |
212 | Meeting Workspace Pages list |
300 | Portal Sites list |
301 | Blog Posts list |
302 | Blog Comments list |
303 | Blog Categories list |
850 | Page Library |
1100 | Issue tracking (00BFEA71-5932-4F9C-AD71-1557E5751100) |
1200 | Administrator tasks list |
2002 | Personal document library |
2003 | Private document library |
Ho aggiunto (in data 9 Ottobre 2010) anche gli ID delle relative feature che installano i template di lista, utili quando si vuole creare un'istanza di lista via feature.
Come dice lui stesso, lo faccio per avere un posto comodo per cercarli.
sabato 3 ottobre 2009
SharePoint Forum in Italiano
Una bella iniziativa, un embrione di community italiana, anche se io spero veda la luce al più presto questo progetto SharePointCommunity.it.
Nota del 11 Luglio 2010: l'indirizzo del forum è cambiato. Quello giusto è il seguente Microsoft SharePoint Forum
lunedì 28 settembre 2009
The Winner is...
La candidatura recita: Cliente ATM, proggettazione e grafica Cultur-e, coord. e sviluppo tecnologico Direz. Sistemi Informativi ATM, soluzione tecnologica Brain Force Italia.
Pierluigi Sacchi (a destra) e Daniele Guarneri (a sinistra) dopo la premiazione, con l'attestato ricevuto per la realizzazione del sito ATM. | |
Daniele Guarneri, Pierluigi Sacchi e Elena Dalla Massara con l'attestato ricevuto per la realizzazione del sito ATM. |
Un ringraziamento speciale a tutti i ragazzi di Brain Force che hanno collaborato per la realizzazione di questo progetto. Un saluto particolare a Lino Miraglia che mi ha sopportato e supportato per tutto il tempo.
Articoli relativi:
Finalmente online
Ringraziamenti
sabato 19 settembre 2009
DataBase Sniffing
Extract MOSS 2007 list info via SQL
venerdì 28 agosto 2009
Guida ad ARF in italiano
Spero che vi sia utile e aspetto commenti e suggerimenti.
Italian ARF Guide
martedì 28 luglio 2009
IFilter
http://blogs.msdn.com/joelo/archive/2008/02/07/ifilter-pack-for-indexing-for-sharepoint-server-2007-search-and-sqlfts.aspx
http://channel9.msdn.com/wiki/desktopsearchifilters/
http://www.ifiltershop.com/dwffilter.html
martedì 14 luglio 2009
Chi cerca trova !?
Chi cerca trova, dicevamo; ma non sempre il detto è vero.
Ultimamente mi è capitato di avere parecchi problemi con il servizio di Search di WSS, ovvero senza eclatanti segnalazioni d'errore mi sono trovato ad avere ricerche prive di risultati. In assenza di errore nell'event viewer e nei file di log è alquanto difficile risalire al problema, inoltre la molteplicità di differenti installazioni complica la cosa e fa sembrare un problema comune un altro problema. Fortunatamente in un caso: WSS 3.0 SP2 a 64 bit installato su Windows Server 2008, qualche segnalazione d'errore mi è stata, appunto, segnalata; in ordine ho ricevuto errori con EventID pari a 10032, 10035, 10038 e 2424.
Event Type: Error
Event Source: Office Server Search
Event Category: Search service
Event ID: 10038
Date: 9/12/2007
Time: 9:14:08 PM
User: N/A
Computer: USCHI4VINSPS1
Description:
Query machine 'USCHI4VINSPS1' has been taken out of rotation due to this error: 0xeb0001d1. It will be retried in 15 seconds. Component: 9eb17ee8-4f59-4bed-a70d-c172ab0857b8
------------------------------------------------------------------------------------------------
Event Type: Error
Event Source: Windows SharePoint Services 3 Search
Event Category: Gatherer
Event ID: 2424
Description: The update cannot be started because the content sources cannot be accessed. Fix the errors and try the update again.
Context: Application 'Search', Catalog 'index file on the search server Search'
"S' io avessi previsto tutto questo, dati causa e pretesto.." avrei cambiato mestiere, comunque sia credo di aver capito che la soluzione di tutti i mali è disabilitare il Loop Back Check. Il sintomo principale lo si può individuare se si prova ad accedere ad una site collection (che non sia la console di amministrazione) dal server in cui è installato SharePoint, il sito non sarà accessibile, metre lo si potrà navigare da qualsiasi altra macchina collegata in rete. Questo è quello che in genere capita con MOSS (401.1 Error When Accessing SharePoint From Server), la stessa anomalia invece in WSS sembrerebbe inficiare anche il servizio di ricerca (anzi al 17/07/2009 ne sono certo). Il tutto sembra essere dovuto ad una patch di windows. Per disabilitare il Loop Back Check ho seguito quanto indicato in questo articolo: "Users experience authentication issues when they access a Web page...". In sintesi:
Impostare DisableLoopbackCheck
Re-enable the behavior that exists in Windows Server 2003 by setting the DisableLoopbackCheck registry entry in the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa registry subkey to 1. To set the DisableLoopbackCheck registry entry to 1, follow these steps on the client computer:
1. Click Start, click Run, type regedit, and then click OK.
2. Locate and then click the following registry subkey: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
3. Right-click Lsa, point to New, and then click DWORD Value.
4. Type DisableLoopbackCheck, and then press ENTER.
5. Right-click DisableLoopbackCheck, and then click Modify.
6. In the Value data box, type 1, and then click OK.
7. Exit Registry Editor.
8. Restart the computer.
Note You must restart the server for this change to take effect. By default, loopback check functionality is turned on in Windows Server 2003 SP1, and the DisableLoopbackCheck registry entry is set to 0 (zero).
Filtrare una lista con regole sulla data
Advanced SharePoint View and Filter techniques
giovedì 9 luglio 2009
Ancora su Feed RSS
pippo.rossi@mail.it
ho messo
pippo.rossi@mail.it (Pippo Rossi)
Infine l'ultimo errore era dovuto ad un namespace inesistente nell'XML generato che si risolve sostituendo l'istruzione
xtw.WriteStartElement(”guid”, page.Title);
con
xtw.WriteStartElement(”guid”, String.Empty);
Dopo queste due semplici modifiche ho rivalidato con successo il feed generato dal mio codice.
giovedì 2 luglio 2009
ARF Guide (1)
ARFConsole
Mostra una console di editing (stile Publishing Site). Ci sono due Control Template per la console; uno per i Publishing Site e uno per i Team Site (WSS e MOSS):
- ArfConsole.ascx
- ArfWssConsole.ascx
Proprietà pubbliche
IsFloating | Booleano per indicare se la console è bloccata o flottante |
Esempio
Inserire nella propria pagina/layout di pagina la dichiarazione del control template da usare e il controllo console;
<@ Register TagPrefix="ARFConsole" TagName="Console" src="~/_controltemplates/ARF/ARFConsole.ascx" %>
<ARFConsole:Console runat="server" IsFloating="True">
giovedì 25 giugno 2009
Feed RSS con SharePoint - Errata Corrige
xtw.WriteElementString(”pubDate”, pages.Created.ToString(”R”));
Questo però genera un problema con i reader (per esempio Outlook). Il metodo ToString della classe DataTime riporta in stringa la data letta da Sharepoint nel formato GMT, ma non aggiorna la data rispetto al meridiano di Greenwich! I reader invece interpretano la data come riferita al meridiano e la correggono in base al fuso orario del paese in cui si trovano, quindi per l'italia in regime di ora legale sommano 2 ore. Capita così di avere item che riportano un orario di insermento superiore all'orario attuale. Per sistemare il problema, bisogna usare l'istruzione seguente:
xtw.WriteElementString(”pubDate”, pages.Created.ToUniversalTime.ToString(”R”));
L'istruzione ToUniversalTime invece riconverte la data rispetto al meridiano di Greenwich.
martedì 23 giugno 2009
Alternative Rendering Framework (ARF)
A breve ho intenzione di parlarvi dei controlli SiteQuery
Rinnovo l'invito a farsi avanti a tutti coloro che avessero informazioni su ARF.
Intanto vi segnalo un embrione di sito documentativo sull'argomento: http://arf.thekid.me/Pages/default.aspx
lunedì 8 giugno 2009
Finalmente online
Sono molto contento di annunciare che ha visto finalmente la luce il progetto che mi ha impegnato per tanti mesi, tutto fatto con SharePoint e che mi ha fornito molti spunti per gli articoli che ho pubblicato.
Andando su www.atm-mi.it potrete vedere il risultato di tanto lavoro.
———————————————————————–
Parlano di noi:
Da oggi i trasporti di Milano viaggiano su SharePoint
venerdì 29 maggio 2009
CAML Query e Stato di un Item
Come sicuramente tutti sanno per testare lo stato di moderazione (_ModerationStatus) di un item in SharePoint con una query CAML si fa in questo modo:
<Query>
<Where>
<Eq>
<FieldRef Name=”_ModerationStatus” />
<Value Type=”ModStat”>Approved</Value>
</Eq>
</Where>
<Query>
Si nota subito che non viene usato un codice (che sarebbe multilingua) ma un valore letterale, quindi se si installa SharePoint in Italiano questa query CAML non funzionerà. I valori possibili forniti da SDK sono:
Member name | Description |
Approved | The last major version of the item is displayed in the public views of the list or document library. |
Denied | The last major version of the item is not displayed in the public views of the list or document library. |
Draft | The item minor version is being edited and is not ready for approval. |
Pending | The decision about displaying the item in public views of the list or document library is pending. |
Scheduled | The decision about displaying the item in public views of list or document library is pending and will be processed by a timer service. |
La traduzione in italiano degli stati dovrebbe essere:
Approvato
Negato
Bozza
In Sospeso
Pianificato
Alla prossima!
mercoledì 27 maggio 2009
WCM Variation & PageLayout
Per un progetto che sto seguendo, mi è capitato di dover affrontare questo problema:
“Avendo attivato le variation in un sito di publishing in cui sono stati crati dei custom web provisioning, ovvero delle classi che si occupano di fare alcune operazioni in fase di creazione di un sito, registrati in una custom site definition, mi è capitato che le home page dei siti ri-creati dal sistema di variation perdessero tutti i page layout associati, matenendo solo quello definito di default. Andando a controllare nella lista Pages le proprietà della default page si vedeva chiaramente che in presenza di contenuti questi venivano renderizzati in modo non corretto perchè mancava il giusto page layout.”
Fortunatamente esiste sempre un pio uomo sulla terra che affronta per primo questi problemi e in questo caso è stato Garry Lapointe che ci mette a disposizione una fantastica collezioni di custom extention per stsadm, tra cui esiste il comando: gl-fixpublishingpagespagelayouturl che permette di riassociare un page layout ad una pagina, ma non solo…
Con questo fantastico comando ho potuto risolvere il mio problema.
giovedì 14 maggio 2009
Scrivere in un SPFolder
Recentemente ho consigliato ad un cliente di utilizzare la possibilità di SharePoint di creare e scrivere in folder invece che in liste, visto che aveva la necessità di memorizzare solo dei dati (immagini) volanti e non permanenti, che dopo poco tempo dovevano essere rimossi. Il folder in questione è stato creato nella site collection per mezzo di una semplice feature che caricava un file di testo nel foder stesso consentendone la creazione. In socondo luogo abbiamo scritto il codice per accedere al foleder ed aggiornarne il contenuto.
Il codice in questione è il seguente:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite elevatedSite = new SPSite(SPContext.Current.Site.ID))
{
using (SPWeb elevatedWeb = elevatedSite.OpenWeb(SPContext.Current.Web.ID))
{
//creo un’istanza di SPfolder che mi aggancia alla cartella creata all’attivazione della FEATURE
SPFolder <NomeOggettoSPFolder> = elevatedSite.RootWeb.Folders["<NomeDellaFolder>"];
elevatedWeb.AllowUnsafeUpdates = true;
//aggiungo il file alla cartella temporaneamente
<NomeOggettoSPFolder>.Files.Add(FileUpload1.FileName, FileUpload1.FileBytes, true);
<NomeOggettoSPFolder>.Update();
elevatedWeb.AllowUnsafeUpdates = false;
}
}
});
E’ importante notare che per aggirare i problemi di sicurezza si è scelti di elevare i diritti di esecuzione e per farlo correttamente si è dovuto creare una Site Collection clone dell’originale e un Web Site clone dell’originale in modo che il contesto risultasse con gli opportuni privilegi. Il resto del codice si commenta da sè, l’unica cosa che posso far notare è l’utilizzo di un controllo .Net per l’upload del file, che nel nostro caso si chiama FileUpload1.
Alla prossima.
venerdì 24 aprile 2009
Accedere alle WebPart di una pagina
Se si ha la necessità di accedere alla form di gestione delle webpart inserite in una pagina è sufficiente porre in query string il seguente parametro “contents=1″.
quindi ad esempio: http://nome_server/Pages/default.aspx?contents=1
martedì 24 marzo 2009
Identificatore univoco per i ListItem
Dovendo recuperare un item di una lista dopo averne fatto un content deploy un mio collega e io ci siamo domandati se ci fosse una proprietà degli item che rimaneva immutata tra sorgente e destinazione: l’abbiamo trovata usando SharePoint Manager. La proprietà in questione è UniqueId; MSDN recita “Gets the GUID that uniquely identifies the item for the internal database” e nulla più. UniqueId è una proprietà di SPListItem. Nel nostro caso i prima battuta usavamo SPContext.Current.Item["GUID"] pensando di aver identificato un valore univoco, invece ci siamo accorti che questo valore con il content deploy variava. Invece utilizzando SPContext.Current.ListItem.UniqueId abbiamo risolto il problema.
Altra cosa interessante è la possibilità di usare questo valore per recuparare un publishing page da una lista Pages tramite Content Query Web Part, infatti con una semplice query CAML del tipo:
<span lang="EN-US"><Where></span><span lang="EN-US">
<Eq>
<FieldRef Name='UniqueId' />
<Value Type='Text'></span><span lang="EN-US">{9C5324A9-BD5D-411C-9F78-7F494BF87985}</span><span lang="EN-US"></Value>
</span> </Eq>
</Where>
è possibile raggiungere il risultato. Sempre usando una Content Query Web Part, estesa da noi in modo da fare override delle proprietà come OvverideQuery, ho scoperto, che istruendo la web part ad estrarre anche la proprietà UniqueId e usando il sitema di debug di Heather Salomon, la proprietà si presenta come segue:
<span lang="EN-US">V:<strong>1;#{9C5324A9-BD5D-411C-9F78-</strong><strong>7F494BF87985}</strong></span>
con lo stesso formalismo di un campo di lookup, dove il numero che precede ;# corrisponde all’ID dell’item nella lista, mentre il codice tra parentesi graffe è l’UniqueId.
Infine segnalo un sistema per esporre lo UniqueId di una pagina di un publishing site in un page layout (comodo anche per altre proprietà del ListItem)
<span lang="EN-US"><SharePointWebControls:ListItemProperty<br />runat="server" id="ListItemProperty1" Property="UniqueId"<br />InDesign="True" /></span>
Alla prossima!
Getting an SPListItem by it’s Unique ID
giovedì 19 febbraio 2009
SharePoint Administrators Summit 2009
Al summit a cui ho partecipato Martedì 17 Febbraio i relatori hanno menzionato una serie di tools utili per sharepoint che vi elenco di seguito (almeno quelli che sono riuscito ad annotarmi):
venerdì 13 febbraio 2009
XSLT Point 0.1
domenica 8 febbraio 2009
Feed RSS con SharePoint - 2/2
Ritorno sull’argomento Feed RSS per segnalare come implementare una pagina custom che generi dei feed RSS versione 2.0 in ambito di siti di publishing; insomma per articoli scritti con il WCM di SharePoint.Per cominciare ho scelto di generare un feed usando come sorgente la lista Pagine/Pages di un sito web il cui GUID mi viene passato in query string. In aggiunta, visto che in una lista Pagine ci possono essere item di tipo diverso ho deciso di farmi passare anche il content type degli item da estrarre. Detto questo per rispettare le specifiche degli RSS 2.0 e per sfruttare SharePoint recupero alcune proprietà memorizzate a livello di site collection, utili per impostare le informazioini che descrivono il canale (channel):
SPWeb root = site.RootWeb;
rss_Copyright = root.AllProperties["vti_rss_Copyright"].ToString();
rss_ManagingEditor = root.AllProperties["vti_rss_ManagingEditor"].ToString();
// Time to Live in minuti
rss_TimeToLive = root.AllProperties["vti_rss_TimeToLive"].ToString();
rss_WebMaster = root.AllProperties["vti_rss_WebMaster"].ToString();
Ora posso cominciare a scrivere il codice per generare il canale:
SPList pages = web.Lists[PublishingWeb.GetPagesListName(web)];
PublishingPage page = null;
// delcare and instantiate XMLTextWriter object
MemoryStream stream = new MemoryStream();
XmlTextWriter xtw = new XmlTextWriter(stream, Encoding.UTF8);
// write out the XML declaration and version 1.0 info
xtw.WriteStartDocument();
// write out the rss xml element “rss” (required)
xtw.WriteStartElement(”rss”);
xtw.WriteAttributeString(”version”, “2.0″);
// write out “channel” element (required)
xtw.WriteStartElement(”channel”);
// write out title, link, and description based on the feed being requested,
// all three elements are required
xtw.WriteElementString(”title”, “RSS Feed”);
xtw.WriteElementString(”link”, web.Url);
xtw.WriteElementString(”description”, web.Description);
// attributi opzionali
xtw.WriteElementString(”generator”, generator);
xtw.WriteElementString(”copyright”, rss_Copyright);
xtw.WriteElementString(”managingEditor”, rss_ManagingEditor);
xtw.WriteElementString(”webMaster”, rss_WebMaster);
xtw.WriteElementString(”ttl”, rss_TimeToLive);
xtw.WriteElementString(”language”, pWeb.Label.Language);
xtw.WriteElementString(”docs”, docs);
xtw.WriteElementString(”pubDate”, pages.Created.ToString(”R”,
CultureInfo.CreateSpecificCulture(”en-US”)));
xtw.WriteElementString(”lastBuildDate”, pages.LastItemModifiedDate.ToString(”R”,
CultureInfo.CreateSpecificCulture(”en-US”)));
L’ultimo passo è generare un elemento ITEM per ogni item della lista.
SPListItemCollection items = pages.Items;
foreach (SPListItem item in items)
{
if (PublishingPage.IsPublishingPage(item) && ValidItem(item,contentTypes))
{
page = PublishingPage.GetPublishingPage(item);
if (page.LastModifiedDate <= DateTime.Now.AddDays(-MaxDays))
{
continue;
}
xtw.WriteStartElement(”item”);
xtw.WriteElementString(”title”, page.Title);
xtw.WriteElementString(”link”, page.Uri.ToString());
xtw.WriteStartElement(”description”);
xtw.WriteCData(item.Properties["PublishingPageContent"].ToString());
xtw.WriteEndElement();
xtw.WriteElementString(”pubDate”, page.CreatedDate.ToString(”R”,
CultureInfo.CreateSpecificCulture(”en-US”)));
xtw.WriteStartElement(”guid”, page.Title);
xtw.WriteAttributeString(”isPermaLink”, “true”);
xtw.WriteString(page.Uri.ToString());
xtw.WriteEndElement();
xtw.WriteEndElement();
}
}
// Close all tags
xtw.WriteEndElement();
xtw.WriteEndElement();
xtw.WriteEndDocument();
xtw.Flush();
string resultXml = null;
using (stream)
{
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
resultXml = reader.ReadToEnd();
}
}
xtw.Close();
return resultXml;
La funzione ValidItem() si occupa di verificare che l’item sia del tipo contenuto voluto. Seguendo questo codice e con qualche linea in più, per esempio per gestire un minimo di cache, è possibile creare il proprio generatore di Feed RSS.
sabato 7 febbraio 2009
Vivisezioniamo il foglio di stile XSLT ContentQueryMain - Prima Parte
In un sabato decisamente umido, per non dire completamente fradicio, vista l’acqua che sta venendo, ho trovato un po’ di tempo per approfondire la conoscenza con le Content Query Web Part (CQWP) e più precisamente con i sui stili XSL. Volevo prendere dimestichezza con gli stili di default per poterne realizzare di miei in modo da personalizzare i risultati della webart nei mie progetti. Il compito è stato facilitato dalla passione che ho nei confronti del linguaggio XSLT, che ho appreso qualche anno fa lavorando per il portale de ‘il Sole 24 Ore’, il cui rendering era completamente basato sulle trasformazioni dei contenuti in XML con XSLT.
Per cominciare mi sono letto un articolo di Microsoft, presente anche nello SDK di MOSS, “How to: Customize XSL for the Content Query Web Part“, che mi ha presentato i tre fogli di stile ContentQueryMain, ItemStyle.xsl e Header.xsl. Descrivendo i template di ItemStyle l’articolo elencava le funzioni usate per facilitare l’estrazione dei dati dal risultato. A questo punto della lettura cresceva sempre di più dentro di me la voglia di capire quale XML produce una CQWP e come funzionano queste funzioni, anche perchè conoscerle può aiutare a semplificare il lavoro e ottenere risultati solidi e in linea con la filosofia del prodotto.
Ecco un elenco delle funzioni OOTB contenute nell’XSL ContentQueryMain:
- OuterTemplate.GetSafeLink
- OuterTemplate.GetSafeStaticUrl
- OuterTemplate.GetColumnDataForUnescapedOutput
- OuterTemplate.GetTitle
- OuterTemplate.FormatColumnIntoUrl
- OuterTemplate.FormatValueIntoUrl
- OuterTemplate.Replace
- OuterTemplate.GetPageNameFromUrl
- OuterTemplate.GetPageNameFromUrlRecursive
- OuterTemplate.GetGroupName
- OuterTemplate.CallPresenceStatusIconTemplate
Queste “funzioni” che in realtà sono dei template xsl aiutano ad estrarre le informazioni in modo corretto dall’elemento xml passato. Ritorna a questo punto la prima delle questioni: recuperare il risultato della query, insomma vedere l’xml prodotto dalla CQWP. Girovangando su internet ho trovato un po’ di spunti. Heather Solomon spiega come vedere le proprietà degli item estratti (ovvero gli attributi dell’elemento row):
“aggiungere nel file ContentQueryMain un proprio template del tipo:”
<xsl:for-each select=”@*”>
P:<xsl:value-of select=”name()” />
</xsl:for-each>
</xsl:template>
Ma questo non mi bastava, volevo avere sottomano un file XML. A questo punto ho deciso di creare un mio foglio di stile partendo dal ContentQueryMain originale e usare la tecnica dell’identity, così ho prodotto questo codice (IdentityContentQueryMain.xsl):
<xsl:output method=”xml” version=”1.0″ encoding=”UTF-8″ indent=”yes”/>
<xsl:param name=”cbq_isgrouping”/>
<xsl:param name=”cbq_columnwidth”/>
<xsl:param name=”Group”/>
<xsl:param name=”GroupType”/>
<xsl:param name=”cbq_iseditmode”/>
<xsl:param name=”cbq_viewemptytext”/>
<xsl:param name=”SiteId”/>
<xsl:param name=”WebUrl”/>
<xsl:param name=”PageId”/>
<xsl:param name=”WebPartId”/>
<xsl:param name=”FeedPageUrl”/>
<xsl:param name=”FeedEnabled”/>
<xsl:param name=”SiteUrl”/>
<xsl:param name=”BlankTitle”/>
<xsl:param name=”BlankGroup”/>
<xsl:param name=”UseCopyUtil”/>
<xsl:param name=”DataColumnTypes”/>
<xsl:param name=”ClientId”/>
<xsl:template match=”/”>
<xml-cqwp>
<params>
<xsl:element name=”cbq_isgrouping”>
<xsl:value-of select=”$cbq_isgrouping”/>
</xsl:element>
<xsl:element name=”cbq_columnwidth”>
<xsl:value-of select=”$cbq_columnwidth”/>
</xsl:element>
<xsl:element name=”Group”>
<xsl:value-of select=”$Group”/>
</xsl:element>
<xsl:element name=”GroupType”>
<xsl:value-of select=”$GroupType”/>
</xsl:element>
<xsl:element name=”cbq_iseditmode”>
<xsl:value-of select=”$cbq_iseditmode”/>
</xsl:element>
<xsl:element name=”cbq_viewemptytext”>
<xsl:value-of select=”$cbq_viewemptytext”/>
</xsl:element>
<xsl:element name=”SiteId”>
<xsl:value-of select=”$SiteId”/>
</xsl:element>
<xsl:element name=”WebUrl”>
<xsl:value-of select=”$WebUrl”/>
</xsl:element>
<xsl:element name=”PageId”>
<xsl:value-of select=”$PageId”/>
</xsl:element>
<xsl:element name=”WebPartId”>
<xsl:value-of select=”$WebPartId”/>
</xsl:element>
<xsl:element name=”FeedPageUrl”>
<xsl:value-of select=”$FeedPageUrl”/>
</xsl:element>
<xsl:element name=”FeedEnabled”>
<xsl:value-of select=”$FeedEnabled”/>
</xsl:element>
<xsl:element name=”SiteUrl”>
<xsl:value-of select=”$SiteUrl”/>
</xsl:element>
<xsl:element name=”BlankTitle”>
<xsl:value-of select=”$BlankTitle”/>
</xsl:element>
<xsl:element name=”BlankGroup”>
<xsl:value-of select=”$BlankGroup”/>
</xsl:element>
<xsl:element name=”UseCopyUtil”>
<xsl:value-of select=”$UseCopyUtil”/>
</xsl:element>
<xsl:element name=”DataColumnTypes”>
<xsl:value-of select=”$DataColumnTypes”/>
</xsl:element>
<xsl:element name=”ClientId”>
<xsl:value-of select=”$ClientId”/>
</xsl:element>
</params>
<result>
<xsl:apply-templates/>
</result>
</xml-cqwp>
</xsl:template>
<xsl:template match=”*”>
<xsl:element name=”{name(.)}”>
<xsl:for-each select=”@*”>
<xsl:attribute name=”{name(.)}”><xsl:value-of select=”.”/></xsl:attribute>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<!–
<xsl:template match=”@* | node()”>
<xsl:copy>
<xsl:apply-templates select=”@* | node()”/>
</xsl:copy>
</xsl:template>
–>
</xsl:stylesheet>
C’è un problema però, non basta questo file per estrarre l’XML, bisogna adottare un altro trucchetto, ho creato un secondo stylesheet xsl che ho chiamato Empty.xsl e che è fatto in questo modo:
<xsl:output method=”xml” version=”1.0″ encoding=”UTF-8″ indent=”yes”/>
</xsl:stylesheet>
Assegnando il primo file alla proprietà MainXslLink e il secondo alle proprietà ItemXslLink e HeaderXslLink si ottiene un xml di questo tipo:
<xml-cqwp>
<params>
<cbq_isgrouping>false</cbq_isgrouping>
<cbq_columnwidth>100</cbq_columnwidth>
<Group/>
<GroupType/>
<cbq_iseditmode>true</cbq_iseditmode>
<cbq_viewemptytext>La query non ha restituito elementi. Per configurare la query per questa web part, <a href=”#” onclick=”javascript:MSOTlPn_ShowToolPane2(’Edit’,'g_a3f67598_8486_4855_bbd1_47a052236458′);”>aprire il riquadro Strumenti</a>.</cbq_viewemptytext>
<SiteId>21eba696-36a0-4ad5-95e8-842c0fe0d0c4</SiteId>
<WebUrl>%2Fit%2Fatmnews%2Fatminforma</WebUrl>
<PageId>5c33b0e5-d576-4d0f-a6d5-afbac1bfdefb</PageId>
<WebPartId>a3f67598-8486-4855-bbd1-47a052236458</WebPartId>
<FeedPageUrl>/_layouts/feed.aspx?</FeedPageUrl>
<FeedEnabled>false</FeedEnabled>
<SiteUrl>http://admin.atm.it</SiteUrl>
<BlankTitle>(Vuoto)</BlankTitle>
<BlankGroup>(Vuoto)</BlankGroup>
<UseCopyUtil>false</UseCopyUtil>
<DataColumnTypes>;Modified,DateTime;Title,Text;Author,User;Editor,User;_Level,Number;Created,DateTime;{1d22ea11-1e32-424e-89ab-9fedbadb6ce1},Counter;FileRef,Lookup;Description,Note;PublishingRollupImage,Image;Comments,Note;</DataColumnTypes>
<ClientId>ctl00_SPWebPartManager1_g_a3f67598_8486_4855_bbd1_47a052236458</ClientId>
</params>
<result>
<dsQueryResponse>
<Rows>
<Row ListId=”{A898ACF6-7C42-441F-99A0-05D322E419EF}” WebId=”{AC38FAD2-8709-42EF-9FCF-7B4A822993A8}” ID=”1″ Title=”" FileRef=”en/giromilano/Pages/default.aspx” _x007B_1d22ea11_x002D_1e32_x002D_424e_x002D_89ab_x002D_9fedbadb6ce1_x007D_=”1″ Modified=”2009-02-06 23:38:26″ Author=”Account di sistema” Editor=”Account di sistema” Created=”2009-02-06 15:28:42″ PublishingRollupImage=”" _Level=”2″ Comments=”" LinkUrl=”http://admin.atm.it/en/giromilano/Pages/default.aspx” PubDate=”Fri, 06 Feb 2009 23:38:26 GMT” ImageUrl=”" ImageUrlAltText=”" Description=”" Style=”Default” GroupStyle=”DefaultHeader” __begincolumn=”True” __begingroup=”False”/>
<Row ListId=”{F7E2272E-75BF-435B-A467-59AEC5A0755C}” WebId=”{22DCC1AB-EE62-46E9-B020-E3D2C50DD325}” ID=”2″ Title=”La missione” FileRef=”en/ilgruppo/chisiamo/Pages/lamissione.aspx” _x007B_1d22ea11_x002D_1e32_x002D_424e_x002D_89ab_x002D_9fedbadb6ce1_x007D_=”2″ Modified=”2009-02-06 17:37:05″ Author=”Account di sistema” Editor=”Account di sistema” Created=”2009-02-06 16:06:02″ PublishingRollupImage=”" _Level=”2″ Comments=”" LinkUrl=”http://admin.atm.it/en/ilgruppo/chisiamo/Pages/lamissione.aspx” PubDate=”Fri, 06 Feb 2009 17:37:05 GMT” ImageUrl=”" ImageUrlAltText=”" Description=”" Style=”Default” GroupStyle=”DefaultHeader” __begincolumn=”False” __begingroup=”False”/>
</Rows>
</dsQueryResponse>
</result>
</xml-cqwp>
Con in mano l’xml prodotto posso finalmente lavora of-line per debuggare i miei stili persoinalizzati. Il prossimo passo sarà creare degli XSL personalizzati a partire dagli originali che siano usabili fuori dal contesto SharePoint, ovvero enibendo le funzioni custom di SharePoint del namespace “cmswrt“, in questo modo avrò piena liberta di esplorare la struttura e le logiche degli XSL. Senza però dar troppo peso al risultato.
Come passare parametri a ContentQueryMain
Estendere le CQWP con funzioni personalizzate
Personalizzare gli Item Styles (Heather Solomon)
domenica 1 febbraio 2009
SharePoint Manager 2007 - alla ricerca dei misteri di WSS e MOSS
Come da titolo il programma SharePoint Manager 2007 (SPM 2007) è un utilissimo tool disponibile su CodePlex che consente di ispezionare tutte le proprietà di SharePoint (sia WSS 3.0 che MOSS 2007). Con SPM 2007 è possibile vedere le Feature attivate sia a livello di Site Collection che a livello di Web, inoltre è possibile avere una visione completa della struttura del sito, dei folder creati (ad esempio “_catalog”) dei content type e delle colonne di sito. Di questi ultimi due oggetti SPM 2007 fornisce anche il codice XML che li descrive, in questo modo risulta veramente semplice estrarre le infoimzioni necessarie per riportare su file system quanto creato con l’interfaccia grafica di SharePoint, ovvero estrarre pezzi di codice CAML per replicare quanto fatto a mano in un progetto Visula Studio. Con questo tool ho avuto modo di scoprire quanto riportato in un post precedente, ovvero che SharePoint memorizzi in alcune proprietà, accessebile tramite SPWeb.AllProperties, i GUID delle liste create alla creazione del sito stesso. Con un po’ di intuito e spirito di osservazione è anche possibile scoprire dei veri e propri tesori, ovvero delle carattesristiche non documentate, che facilitano alcuni passi dello sviluppo, per esempio è possibile escludere un sito dalla Global Navigation semplicemente impostando un prorpietà tra quelle presenti in SPWeb.AllProperties:
// _GlobalNavigationExcludes property contains a delimited string of
// GUIDs identifying the Id of each site to be excluded from global
// navigation
webSite.AllProperties["__GlobalNavigationExcludes"]
Quindi impostando questa proprietà con un elenco di GUID separati da punto e virgola (;) si può escluderli dalla global navigation del sito in cui viene impostata la proprietà. Esiste anche la proprietà “__CurrentNavigationExcludes”
, ma non l’ho provata. Sempre tramite SPM 2007 ho potuto ricavare utili informazioni per scrivere il codice personalizzato che genera Feed RSS per un sito di Paublishing, che ho già menzionato e che vi descriverò in seguito.
Spero di avervi dato informazioni utili e mi aspetto qualche commento di conferma su quanto detto o delle smentite se ho riportato informazioni errate. Di certo mi piacerebbe sapere se l’utilizzo diretto di queste proprietà ha qualche controindicazione.
Automate Web App Deployment with the SharePoint API
sabato 24 gennaio 2009
Ringraziamenti
Voglio ringraziare Elisabetta Sasselli e Caludio Brotto di GreenTeam, con cui ho collaborato per un recente progetto e che mi hanno insegnato molto su SharePoint. Con la loro competenza e la loro passione mi hanno spinto inconsapevolmente ad iniziare questa avventura di blogger, facendomi apprezzare sempre più, sia il prodotto che gli sforzi fatti per impararlo.
GRAZIE.
giovedì 22 gennaio 2009
Feed RSS con SharePoint - 1/2
Usando il WCM di SharePoint mi sono dovuto occupare della gestione dei feed rss. SharePoint OOTB genera feed compatibili con la versione 2.0 di RSS (Specifiche RSS 2.0) usando, per quanto ho potuto vedere, due distinte pagine aspx:
- Feed.aspx: usata dalle Content Query Web Part per esporre un feed rss dei risultati della query
- ListFeed.aspx: usata delle liste per esporre un feed del loro contenuto
Come tutti gli strumenti OOTB, non sempre si adeguano alle esigenze di progetto, nel nostro caso (sito di publishing) i feed generati dalle liste non vanno bene, in quanto i link generati fanno riferimento agli item della lista stessa, i feed generati dalle CQWP andrebbero bene se non fosse che non si accordano con le specifiche grafiche. La bella notizia è che costruire un proprio feed RSS non è complicato, pertanto per soddisfare le esigenze di progetto ho implementato una mia pagina aspx da mettere nella cartella LAYOUTS di SharePoint. Di questo però parlerò un altro giorno, adesso scappo a dormire…