EventReceiver, modificare i valori delle colonne con ItemAdding

by matteo 30. agosto 2012 14.28

Recentemente mi è capitato di dover lavorare su un sito in cui erano presenti diversi calendari e ogni volta che un elemento era inserito o modificato su uno di questi calendari doveva essere inviata una mail che aveva sempre la stessa struttura, indipendentemente dal calendario.

É stato quindi creato un Reusable Workflow sul Content Type di base del calendario e all’interno di questo workflow è stata inserita l’azione che invia la mail. Nel corpo della mail tra le altre cose venivano riportate la data di inizio e la data di fine evento (2 colonne predefiniti degli elementi della lista Calendario).

Con sorpresa effettuando dei test ho notato che la data di fine era corretta, mentre come data di inizio compariva 01/01/0001 00:00, cosa che non andava per niente bene.

Dopo una breve ricerca sul web ho scoperto che si tratta di un piccolo bug di SharePoint (non so se solo della versione 2010 o anche del 2007).

Per ovviare il problema ho tentato un po’ di strade e quella che ha funzionato (che non ritengo essere la migliore, ma per problemi di tempo non ho potuto approfondire) è la seguente.

Ho creato un nuovo Content Type partendo dal Content Type “Event” (quello predefinito per le liste Calendario) e ho aggiunto una colonna di tipo testo che ho chiamato “Text Start DateTime”, dopodichè ho creato da codice un EventReceiver che scattasse sulle liste di tipo Calendario (ListTemplateId=”106”).

Su questo EventReceiver sono andato ad agire sugli eventi ItemAdding e ItemUpdating, ovvero quelli che scattano prima che le modifiche siano persistite sul database.

Il codice che ho usato è molto semplice ed è il seguente:

public class MyEventReceiver : SPItemEventReceiver {
    /// <summary>
    /// An item is being added.
    /// </summary>
     public override void ItemAdding(SPItemEventProperties properties) {
         SetItemTextStartDateTime(properties);
         base.ItemAdding(properties);
     }
 
     /// <summary>
     /// An item is being updated.
     /// </summary>
     public override void ItemUpdating(SPItemEventProperties properties) {
         SetItemTextStartDateTime(properties);
         base.ItemUpdating(properties);
     }
 
     private void SetItemTextStartDateTime(SPItemEventProperties properties) {
         if (properties.List.Title == "Nome Lista") {
             try {
                 EventFiringEnabled = false;
                 string textStartDateTime = properties.AfterProperties["EventDate"] == null ? string.Empty :
                     Convert.ToDateTime(properties.AfterProperties["EventDate"]).ToShortDateString() + " " +
                     Convert.ToDateTime(properties.AfterProperties["EventDate"]).ToShortTimeString();
                 properties.AfterProperties["Text_x0020_Start_x0020_DateTime"] = textStartDateTime;
             }
             catch (Exception ex) {
                 // Gestione Errore
             }
             EventFiringEnabled = true;
         }
     }
}

Tags:

eventreceiver | sharepoint

SharePoint 2010, recuperare il valore di un parametro dalla querystring via javascript

by matteo 23. luglio 2012 09.46

Oggi ho scoperto una funzione javascript che fa parte delle librerie standard di SharePoint 2010 (e forse anche in quelle di MOSS 2007) e più precisamente che si trova nel file init.js utile quando si ha la necessità di recuperare un parametro dalla querystring.

Normalmente utilizzavo una funzione scritta da me, ma credo sia meglio utilizzare quella fornita da SharePoint.

La funzione in questione è la GetUrlKeyValue(keyName, bNoDecode, url).

I tre parametri della funzione sono:

keyName: nome del parametro querystring del quale recuperare il valore;

bNoDecode: se true il valore della funzione non viene decodificato, diversamente il valore viene decodificato;

url: indirizzo dal quale estrarre il valore del parametro querystring.

Se il parametro url non viene passato la funzione utilizza l'indirizzo corrente.

Ad esempio se volessi recuperare il valore del parametro Source decodificato dall'indirizzo della pagina sulla quale mi trovo dovrei utilizzare la funzione in questo modo:

var source = GetUrlKeyValue("Source", false);

 

Tags: ,

javascript | sharepoint

SharePoint e Office 2013 in Beta

by matteo 17. luglio 2012 09.30

Ieri Microsoft ha annunciato la disponibilità delle versioni beta di SharePoint 2013 e di Office 2013.

Potete scaricare le versioni che vi interessano da qui:

Microsoft Download Center

Sono disponibili anche i primi training video su MSDN (Developer) e su TechNet (IT Pro), di seguito i link:

MSDN: Developer Training Video per SharePoint e Office 2013

TechNet: IT Pro Training Video per SharePoint e Office 2013

Tags:

sharepoint 2013

Colonna Type (icon linked to document) in SharePoint 2010

by matteo 13. luglio 2012 10.52

Dopo la migrazione di una farm SharePoint dalla versione 2007 alla versione 2010 ci siamo accorti che sulle form libraries si verificava un comportamento strano.

Su tutte le view di queste form libraries la prima colonna era la colonna Type (icon linked to document) poichè i nomi che venivano generati per i form non erano molto user friendly e quindi si era preferito non visualizzarlo. In questo modo facendo click sull'icona della colonna Type si veniva riportati al form InfoPath correlato.

Dopo la migrazione però questo comportamento è cambiato e su SharePoint 2010 il click sull'icona della colonna Type non fa nient'altro che selezionare la riga sulla form library.

Esiste un workaround per riportare il comportamento a quello di SharePoint 2007 ed è descritto nel seguente articolo di Microsoft:

http://support.microsoft.com/default.aspx?scid=kb;en-US;2457975

In questo modo anche su SharePoint 2010 cliccando sull'icona della colonna Type si verrà correttamente portati al form InfoPath.

Tags: , ,

sharepoint | infopath

Errore Could not load type IDataServiceUpdateProvider utilizzando i REST Services con SharePoint 2010

by matteo 9. luglio 2012 11.01

Abbiamo sviluppato delle applicazioni che fanno uso del REST Services di SharePoint 2010 e testando queste applicazioni sul server di produzione ci siamo imbattuti nell'errore 'Could not load type 'System.Data.Services.Providers.IDataServiceUpdateProvider' from assembly 'System.Data.Services, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

Abbiamo controllato che effettivamente il file esistesse nella GAC e questo c'era, poi fortunatamente ci è venuta in mente una nota letta sul fantastico libro "SharePoint 2010 as a Developement Platform" edito da Apress che parlava di un update dei Data Services che non è parte del sistema operativo (per chi ha il libro può trovare questa nota a pagina 261).

Purtroppo i link presenti sulla pagina non sono corretti (almeno quello per Windows Server 2008R2) e così ecco quelli giusti:

Windows Server 2008 R2 e Windows 7: http://www.microsoft.com/en-us/download/details.aspx?id=2343;

Windows Server 2008 e Windows Vista: http://www.microsoft.com/en-us/download/details.aspx?id=5121.

Dopo l'installazione dell'update e il riavvio del server tutto ha funzionato correttamente.

Tags: ,

Disabilitare Page Event Validation in SharePoint 2010

by matteo 5. luglio 2012 17.24

Sviluppando delle visual web part per SharePoint 2010 che fanno un intensivo utilizzo di AJAX e Javascript può capitare di incorrere in questo errore:

"Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation"

Per non incorrere in problemi di sicurezza la soluzione ottimale sarebbe quella di registrare tutti gli eventi che modificano il render della pagina al postback con il metodo ClientScripManager.RegisterForEventValidation.
In alcuni casi ciò non è possibile perchè gli elementi che scatenano gli eventi che modificano il render della pagina non sono conosciuti a priori e non è possibile accedervi da codice lato server.

Essendo in una visual web part si lavora in buona sostanza su un controllo ASCX e quindi non è possibile intervenire sulla pagina e disabilitare la validazione degli eventi solo sulla pagina stessa.

L'unica strada che resta da percorrere è quella di disabilitare la validazione degli eventi a livello di file di configurazione. Bisogna fare attenzione a tutti i possibili rischi per la sicurezza ai quali ci si espone con questa scelta ma, specialmente per ambienti Intranet può non rappresentare un problema.

Per disabilitare la validazione degli eventi a livello di configurazione bisogna portarsi nella directory virtuale IIS della nostra Web Application SharePoint (solitamente C:\inetpub\wwwroot\wss\VirtualDirectories\...) e editare il file web.config. Dopo aver trovato il tag <pages... aggiungere un attributo enableEventValidation="true", salvare il file e il gioco è fatto!

Tags:

I Display Form creati con SharePoint non visualizzano gli allegati

by matteo 29. giugno 2012 11.13

Quando si crea un Display Form custom tramite SharePoint Designer 2010 (non so se accade anche con il 2007, non ho provato) di default non viene generato il controllo per la visualizzazione di eventuali allegati.

Per ovviare al problema i passi da seguire sono i seguenti:

- Identificare il tag <xsl:template name="dvt_1.rowview">, all'interno del quale si trova il markup per visualizzare tutte le colonne della lista.

- All'interno del tag <xsl:template name="dvt_1.rowview"> identificare il primo tag <table>.

- Portarsi alla fine del markup contenuto nel tag <table>e posizionarsi dopo l'ultima riga </tr>.

- Inserire in questo punto il seguente codice:

<tr>
<td nowrap="true" valign="top" class="ms-formlabel" width="20%">
<SharePoint:FieldLabel ControlMode="Display" FieldName="Attachments" runat="server"/>
</td>
<td valign="top" class="ms-formbody" width="80%">
<SharePoint:FormField runat="server" id="AttachmentsField" ControlMode="Display" FieldName="Attachments" __designer:bind=""/>
</td>
</tr>

A questo punto gli allegati dovrebbero vedersi correttamente anche sul Display Form Custom.

Tags: , ,

Errore 404 Not Found caricando file grandi su SharePoint 2007

by matteo 5. giugno 2012 09.53

Nei giorni scorsi un cliente ci ha fatto presente un problema che si verificava quando cercava di fare l'upload di un file di circa 30MB su una document library di SharePoint 2007.

L'upload partiva correttamente, poi quando sembrava che il browser dovesse riportare alla pagina principale della document library portava invece ad una pagina che restituiva l'errore 404 - Not Found.

Dopo una breve indagine con l'immancabile Google abbiamo trovato questo articolo della KB Microsoft: http://support.microsoft.com/kb/942074.

Sembra che su IIS 7 per impostazione di default la dimensione massima dei file gestiti sia di circa 28MB (30000000 / 1024 / 1024).

Il server di front end sul quale gira questa installazione di SharePoint è proprio un Windows 2008 Server (Non R2) quindi con IIS 7 installato.

Abbiamo seguito le istruzioni dell'articolo con una piccola modifica; il nostro file applicationhost.config non conteneva un nodo <requestLimits> quindi abbiamo dovuto aggiungerlo prima del tag di chiusura della sezione <requestFiltering> in modo che rimanesse all'interno della sezione requestFiltering stessa.

Dopo averlo aggiunto specificando l'attributo maxContentAllowedLength desiderato (il valore deve essere espresso in byte) siamo riusciti a caricare il file che dava problemi.

Tags: , ,

sharepoint | upload file

SharePoint list event receiver e problemi con Afterproperties

by matteo 12. aprile 2012 09.46

Una caratteristica di SharePoint molto comoda utilizzabile durante lo sviluppo è rappresentata dagli EventReceiver.

Grazie agli EventReceiver è possibile agganciare del codice personalizzato ad eventi che si scatenano sulle liste o sulle document library di SharePoint quando un elemento viene inserito, aggiornato, eliminato o quando se ne modificano gli allegati.

Stavo sviluppando uno di questi EventReceiver che doveva controllare se alcuni campi di un elemento di una lista erano stati modificati e in caso affermativo impostare un flag in modo da avvisare graficamente l'utente che queste modifiche erano state fatte.

Per controllare se i campi erano stati modificati avevo fatto l'override dell'evento ItemUpdating, che scatta prima che le modifiche fatte all'elemento vengano scritte sul database di contenuto.

Su ItemUpdating andavo a confrontare i valori dei campi che mi interessavano trasformandoli prima in stringhe in modo da poter gestire la comparazione. Per conoscere il valore prima della modifica e quello dopo la modifica usavo, rispettivamente la proprietà ListItem e la proprietà AfterProperties dell'oggetto SPItemEventProperties properties come documentato qui.

Nel dettaglio i campi che dovevo confrontare erano di tipo Testo, Data e Persona (sia a singolo valore che multivalore).

Il codice usato era di questo tipo:

string oldValue = properties.ListItem["FieldName"] == null ?
    string.Empty : properties.ListItem["FieldName"].ToString();
string newValue = properties.AfterProperties["FieldName"] == null ?
    string.Empty : properties.AfterProperties["FieldName"].ToString();
if (oldValue != newValue) {
    // Imposta flag di modifica
}

Testando il funzionamento di questo EventReceiver ho notato delle anomalie; il flag che indicava la modifica dei dati veniva settato anche quando i campi controllati non venivano modificati.

Facendo un po' di test ho scoperto 3 tipologie di comportamenti strani (probabilmente ce ne saranno altri, se li scoprite fatemelo sapere...):

  1. AfterProperties NULL

    Valore del campo sulla proprietà ListItem (vecchio) corretto, mentre sulla proprietà AfterProperties (nuovo) è uguale a NULL

    Purtroppo non sono riuscito a trovare nessuna documentazione in merito e ho ipotizzato che quando ci si trova in questo caso il valore del campo non sia stato modificato.

  2. Campi di tipo Person

    Sui campi di tipo person il valore del campo sulla proprietà ListItem (vecchio) è nel formato ID;#Nome Completo Utente (es. 1;#Mario Rossi), mentre sulla proprietà AfterProperties (nuovo) viene riportato solo l'ID oppure in alcuni casi viene riportato nel formato ID;#Dominio\UserName (es. 1;#MICROSOFT\mrossi).

    In questo caso per risolvere il problema ho tenuto conto solo dell'ID, in questo modo:

    if (properties.ListItem["FieldName"].ToString().IndexOf(";#") >= 0) {
        property = properties.ListItem["FieldName"].ToString().Substring(0, properties.ListItem["FieldName"].ToString().IndexOf(";#"));
        if (properties.AfterProperties["FieldName"].ToString().IndexOf(";#") >= 0) {
            if (properties.AfterProperties["FieldName"].ToString().IndexOf(";#") == properties.AfterProperties["FieldName"].ToString().LastIndexOf(";#")) {
                afterProperty = properties.AfterProperties["FieldName"].ToString().Substring(0, properties.AfterProperties["FieldName"].ToString().IndexOf(";#"));
            }
        }
        if (afterProperty.Length == 0)
            afterProperty = properties.AfterProperties["FieldName"].ToString().Trim();
    }
    
  3. Campi di tipo Data/ora

    L'ultimo problema riscontato riguardava i campi di tipo Data/ora. Il valore del campo sulla proprietà ListItem (vecchio) è nel formato dd/MM/yyyy hh:mm:ss (es. 12/04/2012 14:30:26), mentre sulla proprietà AfterProperties (nuovo) viene riportato nel formato yyyy-MM-ddThh:mm:ssZ (es. 2012-04-12T14:30:26Z).

    In questo caso per risolvere il problema ho convertito come prima cosa i 2 valori in DateTime e poi li ho confrontati.

    if (properties.ListItem["FieldName"].GetType() == typeof(DateTime)) {
        DateTime dtProperty = Convert.ToDateTime(properties.ListItem["FieldName"]);
        DateTime dtAfterProperty = Convert.ToDateTime(properties.AfterProperties["FieldName"]);
        property = dtProperty.ToShortDateString();
        afterProperty = dtAfterProperty.ToShortDateString();
    }
    

Spero che queste informazioni possano essere utili a qualcuno...

Tags: ,

About the author

Something about the author

Month List

Page List