Ricersca sviluppatore Umbraco su Milano


"Sporco" il wall perchè credo che il forum dell'area lavoro di UGI non sia poi così frequentato... :)

Cerchiamo uno/due sviluppatori .NET con esperienza C# e (graditissima se ci fosse) conoscenza Umbraco (XSLT, custom datatype ed extension) a Milano, per aumentare il nostro organico interno. Il contratto e di assunzione, stiamo cercando persone con conoscenza ma da formare sui progetti interni e sulle problematiche del nostro team. Se siete interessati contattatemi tramite il contatto del blog, tramite twitter (ghizzardia), o sul sito di Umbracoitalia.

author: Alessandro Ghizzardi | posted @ giovedì 16 giugno 2011 21:01 | Feedback (0)

Umbracoitalia ha i forum!


Dopo lunga gestazione, abbiamo inserito la funzionalità di forum in Umbracoitalia.
Finalmente c'è un posto tutto italiano per scambiarsi problemi (e soluzioni) basate su questo CMS.

Li abbiamo "lanciati" online a forza, quindi saranno magari pieni di bug... segnalateceli :)

author: Alessandro Ghizzardi | posted @ giovedì 7 aprile 2011 20:56 | Feedback (2)

[Umbraco] Bug nel cut & paste da word in 4.6.1


La versione 4.6.1 di Umbraco è uscita con alcuni bug minori relativi alla parte editoriale.
Uno dei più noiosi è un bug nel TinyMCE relativo al cut&paste da word. Il bug è stato risolto nella versione 4.7, ma per chi non riuscisse ad upgradare in tempo, trovate qui i dati relativi al bug ed anche il file javascript per fixare il problema.

author: Alessandro Ghizzardi | posted @ giovedì 7 aprile 2011 20:54 | Feedback (1)

Aprile...


... ma che succede ad Aprile? Perchè tutte le scadenze di tutti i progetti di tutti i clienti sono ad Aprile? Ma capita solo a me o anche a qualcun'altro??

P.S.... si, sono ancora vivo! Non credavate eh? :)

author: Alessandro Ghizzardi | posted @ mercoledì 6 aprile 2011 19:50 | Feedback (8)

[Umbraco] Umbracoitalia finalmente online!



Oddio.. in realtà è già dal 14 Maggio che siamo online…

Ma le mie (note) manie di perfezionismo mi hanno portato ad attendere per il “lancio” ufficiale.
Il portale pubblicato un mese fa aveva alcune carenze (registrazione, sezione eventi, spazio dei partner) che mi hanno praticamente costretto ad aspettare oggi. Ora, appena finito la pubblicazione delle nuove sezioni, dopo aver perso diverse notti posso finalmente invitarvi a visitare il sito di Umbracoitalia, che presto si arricchirà di nuovi articoli e informazioni riguardanti questo splendido CMS.

Technorati Tags: ,

author: Alessandro Ghizzardi | posted @ mercoledì 16 giugno 2010 20:37 | Feedback (1)

[OT] Breve assenza…



Sono stato un pò ingrato nei confronti di questo blog, nelle ultime settimane.

Molti di voi avranno notato la mia assenza, molti altri no… forse più no :) In realtà in questo caso il lavoro c’entra ma relativamente, il grande colpevole è il mio impegno in un progetto community che, teoricamente, è già partito… ma ancora in sordina, perchè da perfezionista come sono preferisco parlarne ufficialmente quando sarà pronto come si deve :)

Nel frattempo ringrazio chiunque abbia già partecipato al progetto (chi lo ha fatto, lo sa :)): io sto per partire per New York finalmente, per una mini meritata vacanza… al mio ritorno, vi aggiornerò ufficialmente sui progetti futuri :)

author: Alessandro Ghizzardi | posted @ mercoledì 26 maggio 2010 12:41 | Feedback (0)

[Weekly Issue] Disabilitare il debug in ASP.NET a livello di server


Qualche post fa avevo evidenziato i principali effetti deleteri dell’avere in produzione un applicativo con il debug abilitato.

Ultimamente (ieri), mi è capitato ancora una volta di trovare un applicativo in produzione da parecchio tempo che, per motivi ancora da chiarire, si è ritrovato con il debug abilitato. Gli effetti sono stati che l’architettura bilanciata su due nodi continuava a cadere, provocando disservizio. Un frontend che fino al giorno prima reggeva tranquillamente un milione e mezzo di pagine viste al giorno, si è ritrovato a non sopportarne più di 400 mila, con gravi danni per l’advertising. Una volta riconfigurato il web.config, tutto è tornato agli antichi splendori.

Per evitare questo problema, ringrazio Simone per avermi segnalato la direttiva di configurazione “deployment”:

<configuration>
   <system.web>
      <deployment retail="true"/>
   </system.web>
</configuration>

Questa direttiva è disponibile solo a livello di macchina (quindi machine.config) e non a livello di applicazione. Come si legge nella reference (e un pò meglio qui dal caro Scott), permette di disabilitare per tutta la macchina il debug ed il trace, mettendosi al riparo da eventuali “errori” dello sviluppatore o, peggio, del building server.

La contropartita è che, se ci fosse mai la necessità di riabilitare il debug per un sito qualsiasi, non è possibile farlo senza cambiarlo per tutto il server… ma in ambienti di produzione collaudati direi che questo è un effetto abbastanza trascurabile, se paragonato ai benefici che porta.

author: Alessandro Ghizzardi | posted @ giovedì 13 maggio 2010 17:21 | Feedback (1)

[Umbraco] Macro o non Macro? Questo è il problema…



Chi di voi ha utilizzato almeno qualche volta Umbraco, conosce sicuramente il meccanismo potente delle macro.

Come probabilmente sapete, le macro hanno la possibilità di essere “cachate” (utilizzano la cache nativa di ASP.NET) per evitare che vengano interpretate ogni volta. Questa funzionalità è, però, tanto utile quanto pericolosa. Il rischio, infatti, è di “abusare” in maniera eccessiva di questa facilitazione, soprattutto quando si parla di macro XSLT.

Un esempio: chiunque lavori in XSLT da più di qualche ora sa che ci sono dei selettori che in generale è meglio evitare. Qualcosa come

$currentPage/ancestor-or-self::node//node

Permette di risalire tutto l’albero di umbraco e prendere _tutti_ i nodi figli, per effettuare magari qualche filtro. Il problema con questo approccio è che, ovviamente, finchè l’albero rimane sotto la quarantina di pagine non ci sono troppi problemi. Con siti medio complessi, il tempo di parsing dell’XML, che può raggiungere svariati megabyte, diventa proibitivo. Come risultato, l’application pool impiega una vita a partire e, quando la cache scade, il sito può subire dei forti rallentamenti a causa di questo genere di istruzioni, poichè Umbraco deve reinterpretare la macro prima di metterla in cache.

Il mio consiglio è: ricordatevi che Umbraco viene fornito con una base dati. Niente ci vieta di “espanderlo” con delle nostre classi. In certi casi può essere necessario creare delle tabelle di appoggio, e caricare i dati “pesanti” con lavori asincroni. In altri casi, può essere semplicemente sufficente leggere direttamente i dati dal database. Ho visto ultimamente fare una query XSLT per restituire l’ultimo contenuto aggiornato… quando in realtà sarebbe bastata una stored procedure che prendeva l’ultimo record con published = 1 dalla tabella cmsDocument, ordinandolo per data. Una query assolutamente banale per un motore come SQL Server, ma che trasposta in XSLT può diventare un vero problema.

In conclusione, pensiamo sempre se non ci sono modi migliori per effettuare operazioni che possono insistere su tutto l’albero dei contenuti, o su una gran parte di essi.

Technorati Tags: ,,,

author: Alessandro Ghizzardi | posted @ martedì 11 maggio 2010 12:08 | Feedback (0)

[Umbraco] Import massivo ed errori di Lucene



Una delle maggiori richieste quando si implementa qualcosa in Umbraco che ha del pregresso è, ovviamente, l’importazione.

Personalmente, mi sono trovato bene con CmsImport (prima noto come UmbImport), un package commerciale che per 99 dollari permette di fare l’importazione “semplice” e, tramite custom action, maneggiare il documento importato in modo da fare virtualmente qualsiasi cosa. A meno che l’autore non abbia aggiornato la documentazione o il blog mentre leggete questo post, vi consiglio di scrivergli per chiedergli esempi: è possibile fare veramente tante cose e lui è molto disponibile ad aiutarvi, ma gli esempi e la documentazione online sono un pò carenti.

Uno dei più “lunghi” problemi che ho avuto nel suo utilizzo è che, oltre i 100 nodi importati, tutto andava in bomba ed iniziavano ad essere lanciate strane eccezioni relative agli indici di Lucene:

System.IO.IOException. The process cannot access the file [path to some lucene index file].

Googlando anche nelle community di Lucene, ho scoperto un comando

Lucene.Net.Store.FSDirectory.SetDisableLocks(true);

Che dovrebbe disabilirate il locking. Altrimenti, da quello che ho capito, il fatto che l’importazione non sia thread safe può fare accavallare le cose (praticamente lo stesso problema che si ha se si usa la funzionalità di reindicizzazione di Umbraco mentre qualcuno pubblica…)

Technorati Tags: ,,

author: Alessandro Ghizzardi | posted @ mercoledì 28 aprile 2010 17:17 | Feedback (0)

[Weekly Issue] SQL Server, clustered index e GUID



Il disegno di un database è un punto centrale per tutte le applicazioni. Nel mondo web, anche visto il funzionamento disconnesso di ADO.NET, è forse ancora più imperativo definire bene le cose prima di incorrere in errori.

Una delle grandi diatribe relative alle tabelle è l’utilizzo delle chiavi primarie. Identity, GUID, chiavi composte… spesso non si sa cosa scegliere! Io, personalmente, cerco sempre di scegliere i GUID, quando il progetto lo consente. Ma non è, come sempre, “LA” soluzione. Bisogna ponderare di volta in volta per l’effettivo utilizzo.

Nel caso, però, si scelgano di utilizzare i GUID, una funzione disponibile da SQL Server 2005 da ricordare assolutamente è NEWSEQUENTIALID(). Direttamente dalla guida:

In SQL Server 2005 and later versions, you can use the NEWSEQUENTIALID() function generate GUIDs in a sequential order to help eliminate this fragmentation.

Questo ci permette di evitare uno dei maggiori problemi nell’utilizzo dei GUID, insieme a quello ovviamente della relativa “grandezza” del tipo di dato.

author: Alessandro Ghizzardi | posted @ martedì 20 aprile 2010 21:31 | Feedback (1)

[Weekly Issue] web.config, <compilation debug=”true”> e produzione



Spesso (troppo) vedo un gran numero di progetti web che finiscono in produzione senza le dovute precauzioni.

La cosa peggiore che si può fare è, quasi certamente, dimenticarsi di cambiare l’attributo “debug” nel web.config quando si pubblica. Vedere

<compilation debug=”true”>
..
</compilation>

nei web.config dei server di produzione dei miei clienti ormai mi da istinti omicidi :)

Molti non lo fanno per pigrizia o perchè “così se c’è un errore, ho informazioni più dettagliate”. Questo approccio è _assolutamente sbagliato_: una forte politica di logging mette al sicuro dagli errori sconosciuti e, se proprio è necessario, si riabilita il debug ma solo per il tempo necessario ad ottenere le dovute informazioni.

Questo perchè, anche se purtroppo molti lo ignorano, tenere il debug abilitato ha un sacco di effetti deleteri, tra cui:

- I file creati nella directory temporanea di ASP.NET sono molti di più in debug che in release, quindi il framework deve gestire piu accessi al file system;
- La batch compilation non funziona. Quindi, invece di compilare tutte le pagine in una cartella, ASP.NET compila file per file... finchè qualcuno non "vede" la pagina questa non viene compilata!
- Le pagine non hanno timeout applicativo. Moooolto pericoloso se ci sono errori di qualsiasi genere che possono inchiodare le richieste (contando che ASP.NET ha richieste limitate, se 10 utenti chiedono una pagina che va in attesa di qualcosa, non viene tirato giù il processo e il server diventa autistico....)

Direi che già questi sono un ottimo motivo per levare quell’inutile direttiva :)

Technorati Tags: ,,

author: Alessandro Ghizzardi | posted @ giovedì 15 aprile 2010 16:41 | Feedback (5)

[Weekly Issue] Header runat=server e doppio tag <title>



Lavorando spesso con siti frontend, il SEO diventa una priorità non trascurabile.

L’ottimizzazione per i motori di ricerca è una delle richieste più pressanti da parte del cliente, e questo porta spesso a dover generare titolo, keyword e abstract direttamente da backend (o, utilizzando un CMS, prendendolo dalle proprietà del documento corrente).

Un problema che ho rilevato è che, interagendo direttamente con l’header runat=”server” e inserendo un tag <title> direttamente a runtime, il ASP.NET si “incasina” e, non sapendo che voi avete aggiunto effettivamente un tag <title> magari nel page_load, lo aggiunge lui. Questo porta ad avere due tag <title>, di cui uno vuoto e uno valorizzato con i vostri dati.

Malgrado non sia effettivamente un errore, e non influisca negativamente sul ranking dei motori di ricerca, può essere poco divertente e far fallire qualche validatore di terze parti. Il consiglio che vi posso dare è di creare comunque un tag title con un dato ID, e di andare a modificare quello con un FindControl. In questo modo, la gestione è anche più pulita.

Technorati Tags: ,,

author: Alessandro Ghizzardi | posted @ mercoledì 14 aprile 2010 16:43 | Feedback (2)

[Weekly Issue] XSLT 1.0 e divisione



Lavorando così tanto con Umbraco, XSLT ormai è diventato un mio secondo linguaggio.

Scendere a patti con la paginazione in XSLT, spesso, può essere un problema. Il problema principale è la mancanza di divisione con resto: idiv è stata introdotta con XSLT 2.0, che purtroppo non è supportato dal Framework ne, quindi, da Umbraco.

L’alternativa è:

- Introdurre un parser XSLT di terze parti e mettersi a modificare il core (come quello di Altova, che è disponibile gratuitamente). Particolarmente complesso :)

- Utilizzare la funzione floor(), che restituisce il numero intero indipendentemente da quello che viene dopo la virgola.

Quindi utilizzando floor() in congiunzione con mod (resto della divisione, che invece esiste anche in XSLT 1.0) possiamo avere il classico vecchio “numero di pagine” senza particolari problemi!

author: Alessandro Ghizzardi | posted @ mercoledì 31 marzo 2010 19:37 | Feedback (0)

[Umbraco] Tips and Tricks



Ci sono molte parti di Umbraco che hanno bisogno di essere… “aiutate” per funzionare correttamente!

Molto si trova con la pratica, molto leggendo blog come il mio :)
Quindi, visto che non sono geloso, vi giro un altro blog da cui ricavo un sacco di informazioni utili, che spesso utilizzo:

http://www.nibble.be/

A discapito dell’estensione, il sito è in comprensibilissimo inglese, e punta molto sull’argomento “startup” di Umbraco, che io spesso posso tralasciare per motivi pratici…

Technorati Tags: ,

author: Alessandro Ghizzardi | posted @ martedì 9 marzo 2010 15:49 | Feedback (0)

[Weekly Issue] ASP.NET, System.Drawing.Image.Save() e Generic Error in GDI+



Utilizzando l’oggetto Image, può capitare di ricevere un errore, abbastanza criptico, che spesso è impossibile da interpretare:

Generic Error in GDI+

Chiaramente, i componenti COM non hanno la buona educazione di avvisarci riguardo a _quale_ sia effettivamente l’errore….
Per fortuna, in ASP.NET le cause per questo errore sono principalmente due:

1: Permessi. Ossia, stiamo cercando di salvare un immagine in un percorso in cui l’utente interattivo non ha i permessi di scrittura. Come al solito, ma non solo in questo caso, è buona norma assicurarsi che i permessi siano corretti soprattutto quando si portano i file dal proprio PC al server di stage/produzione

2: Si sta chiamando il metodo Save() passandogli il full path del file. Non so perchè, ma in quasi tutte le prove che ho fatto questo metodo fallisce. Purtroppo, non in tutte. Il giorno in cui capirò perchè sarò, probabilmente, un uomo felice. Nel frattempo, ostento finta felicità utilizzando un oggetto FileStream:

using (FileStream fileStream = System.IO.File.Create(filePath))
{
   img.Save(fileStream, ImageFormat.Jpeg);
}

In questo modo, di solito, non fallisce :)

author: Alessandro Ghizzardi | posted @ giovedì 4 marzo 2010 17:04 | Feedback (4)

[Weekly Issue] DataReader.GetOrdinal e invalid column name



Mi è capitato un problema bizzarro, ultimamente, uno dei tanti in cui mi sto scontrando lavorando con siti con alto traffico di utenti.

Il problema in questione era che il DataReader, improvvisamente, è “impazzito”, restituendo una System.IndexOutOfRangeException nel metodo GetOrdinal. In pratica, mi diceva che nel set di dati restituito mancava la colonna che cercava di leggere. Peccato che, nel metodo in questione, la colonna ci fosse, la stored fosse corretta… insomma, funzionasse tutto “normalmente”. Come nel classico dei bachi, il problema si presentava in maniera assolutamente randomica. Quindi, per esempio, andava perfettamente in 10 casi, l’undicesimo esplodeva.

Il progetto in questione utilizza un mio “storico” data access helper, utilizzato ormai in una marea di progetti anche con più traffico, e più importanti, di questo. Quindi, ho cercato in altri punti il problema, senza arrivare a soluzione alcuna. Mi sono quindi rimesso in discussione, ed ho ricontrollato il data access, trovandolo senza falla (per fortuna!). L’unico dubbio che mi è, per fortuna, venuto, riguarda il fatto che il progetto era gestito da un’altra azienda, cui ho dato alcune dritte, ma che poteva tranquillamente aver male interpretato le mie istruzioni. Quindi, vado a rivedere _come_ è stato utilizzato il mio data access… ed ho trovato la magagna!

In sostanza, il mio data access ha la possibilità di operare in ambiente multi transazionale. Aprendo una transazione, ed una connessione, il data access si predispone a “transazionare” tutti gli oggetti di business in un determinato contesto. Senza questa funzionalità attiva, il data access si predispone per aprire, utilizzare, e richiudere subito la connessione in modo da rimandarla nel pool. L’utilizzo improprio, invece, ha fatto in modo che la connessione venisse aperta _fuori da un contesto transazionale_, e poi di fila venivano chiamati 5 o 6 metodi che riempivano un reader e lo consumavano, chiudendolo ma senza utilizzare CommandBehavior.CloseConnection. Alla fine di tutto, veniva chiusa la connessione.

Senza nessun contesto transazionale attivo, e vista l’intrinseca concorrenzialità di un progetto web, succedeva che i dati del datareader venissero “mischiati” da una chiamata arrivata tra la lettura e l’effettivo consumo del reader. Ho trovato una buona spiegazione di questo problema in questo post sul forum. Per risolvere è bastato rimuovere le connessioni aperte e chiuse in maniera programmatica, e lasciare fare a lui il suo lavoro.

E con questo siamo a due problemi di concorrenza su thread nel corso di una sola settimana… è un segno che, in giro, si fa troppa poca attenzione a questo genere di problematiche? :)

author: Alessandro Ghizzardi | posted @ mercoledì 3 marzo 2010 16:25 | Feedback (0)

[Weekly Issue] Generic collection & Multithread



In uno dei tanti progetti che sto seguendo, mi è capitato un errore di quelli che nessuno vorrebbe mai avere: l’applicativo schizza come una lippa ma, improvvisamente, la CPU schizza al 100% (su un server con 16 core e 16 giga di ram…) e rimane li, inchiodata, per quasi un minuto. Poi va giù, senza generare errori rappresentativi, e ritorna a funzionare… per non si sa quanto!

Abbiamo passato differenti giornate a cercare di capire il problema. Alla fine, siamo abbastanza sicuri di aver isolato la causa: l’utilizzo di una cache esterna basata su Dictionary, “falliva” in ambiente multithread in quanto si era dimenticata che le Generic Collection non sono thread-safe. Come dice giustamente in questo post, la funzionalità è stata volutamente lasciata fuori. Peccato che, in certi casi, un FindElement su una collection che è magari stata modificata nel frattempo da un altro thread, può portare .NET a un loop infinito (e questo, però, vorrei tanto capire per quale motivo dovrebbe succedere….). Questo post mi ha abbastanza aperto gli occhi sul motivo per cui si sono rivelati i problemi!

Modale della favola: fate attenzione quando utilizzate tutti gli oggetti, anche quelli forniti dal Framework, e controllate bene se sono thread-safe, in caso vogliate usarli in applicativi con alto traffico! Ora, rimane solo da vedere se la cosa risolve veramente :)

author: Alessandro Ghizzardi | posted @ lunedì 1 marzo 2010 19:06 | Feedback (2)

[Umbraco] Template, XSLT e parametri



Probabilmente molti di voi, usando Umbraco, si appoggiano a dei template XSLT per gestire le proprie macro. Se già non lo fate, iniziate a farlo… la gestione dei template è importante, e permette di mantenere gli XSLT relativamente semplici da gestire.

Una comodissima funzionalità dei template XSLT è la possibilità di richiamare un dato template, passando dei parametri. Questi parametri possono essere passati, o avere un valore di default che verrà utilizzato all’interno del template stesso.

Per dichiarare il template con i parametri, la sintassi è

<xsl:template match="node" mode="list">
    <xsl:param name="startingLetter">A</xsl:param>
    <!-- do something here –>
</xsl:template>

Per richiamarlo, invece, la sintassi è

<xsl:apply-templates select="$currentPage" mode="list">
    <xsl:with-param name="startingLetter">
        <xsl:value-of select="$startingLetter" />
    </xsl:with-param>
</xsl:apply-templates>

In questo modo, se non si passa il parametro, il template prenderà il valore di default “A”.

author: Alessandro Ghizzardi | posted @ giovedì 25 febbraio 2010 16:51 | Feedback (0)

[OT] Finally live… Vogue Italia!



… e speriamo che sia l’inizio di un periodo con più sonno! :)

E’ online da pochi minuti il nuovo sito di Vogue Italia, la mia ultima fatica in Umbraco! Così capirete cosa intendo quando parlo di “siti impossibili” usando Umbraco :)

author: Alessandro Ghizzardi | posted @ mercoledì 24 febbraio 2010 01:07 | Feedback (5)

[Umbraco] Remove old versions



Umbraco ha alcune grandi pecche. Una delle più grandi è la crescita, a volte incontrollata, della base dati. Questo succede perchè per ogni salvataggio, Umbraco si tiene una versione di tutte le proprietà specificate per un DocumentType, nella tabella cmsPropertyData. Questo è comodissimo dal punto di vista redattoriale, ma per siti con grande ricambio di dati (come le testate giornalistiche che sto seguendo in questo periodo) si traduce in una crescita veramente esponenziale. Inoltre, anche la tabella umbracoLog cresce a dismisura, poichè non è possibile filtrare il livello di verbosity: o si spegne tutto, o ci si becca qualsiasi operazione loggata (salvataggio, pubblicazione, etc). Su Style.it, lanciato a fine Novembre, in soli tre mesi di attività eravamo arrivati a 4gb di dati.

Per la umbracoLog, è necessario cancellare la tabella. Per le versioni vecchie, invece, purtroppo non è prevista (per ora) una funzionalità di cancellazione delle versioni vecchie. E’ quindi necessario farlo a mano. In questo post, viene spiegato quali istruzioni SQL lanciare per farlo. Dopo aver cancellato le ultime versioni ed eseguito il clear del log, il database si è ridotto da 4gb a 400mb.

Esistono anche dei tools offline, la maggior parte non sono aggiornati. I più “recenti”, cioè quelli che dicono di funzionare sulla 4.x, sono i Client Tools for Umbraco, che però purtroppo non sono mai riuscito a far funzionare… se qualcuno ci riesce me lo faccia sapere :)

Io personalmente ho una stored, grazie all’aiuto di Xeed, che prende le ultime versioni precedenti ad una certa data, e cancella i relativi dati. Molto utile per evitare di zappare tutti i contenuti alla redazione: lasciargli solo l’ultima settimana di aggiornamenti è piu che sufficente per salvare spazio, e mantiene un certo livello di sicurezza agli editori.

author: Alessandro Ghizzardi | posted @ martedì 23 febbraio 2010 19:53 | Feedback (2)