Da un po' di tempo lavoro con e, nonostante tutti i conosciuti problemi, in azienda siamo riusciti ad addomesticarlo (o forse lui ha addomesticatio noi :P) e riusciamo a trarne vantaggio, nei limiti da esso imposti. In attesa della prossima versione che pare risolva buona parte dei problemi (ma al momento lo dico solo per sentito dire e non per esperienza diretta), vorrei darvi un tip su come gestire il merge di file EDMX (il Model di Entity Framework per intenderci) che se preso nel verso sbagliato è prolifico di errori.

L'origine del problema è da individuarsi in una formattazione "allegra" del file XML per cui il tag di chiusura di alcune sezioni viene messo in coda all'ultimo elemento figlio e non sulla riga successiva. Un esempio lo si vede nella parte superiore della seguente figura.

Comparazione Per quanto strano possa sembrare questo fatto mette in crisi il merge (io mi riferisco a Team Foundation Server) e spesso (o soprattutto) la persona che lo sta compiendo. Può accadere che aggiungendo una property ad una entità ci si trovi nel caso della parte inferiore della figura soprastante. Come si vede la proprietà Date diventa l'ultima dell'EntityType. Un merge manuale comporta la copia di entrambe le righe 107 e 108 ma come spesso accade (e direi "umanamente accade") si tende a copiare solo la riga 108 ottenendo quanto segue:

merged Inutile dire che il risultato è un errore di compilazione che (complice l'entity designer di Visual Studio) si traduce nel fallimento della generazione del codice e in qualche centinaio di incomprensibili errori... tutto ciò significa solo una cosa: tempo perso.

Dopo esserci caduto svariate volte ho elaborato una mia "strategia" personale per il merge di file edmx. L'unica cosa "sana" da fare è prevenire questo genere di errori aprendo manualmente da Visual Studio i due file da comparare nell'editor XML e grazie alla preziosa combinazione di tasti CTRL+SHIFT+D riformattare l'XML correttamente. Una operazioni di pochi istanti, che non richiede nemmeno l'apertura della solution, che però fa evitare errori inutili e forieri perdite di tempo. Una volta riformattati i file con questa combinazione infatti il codice sarà lineare e, sembra impossibile ma è così, si otterranno anche meno merge manuali.


Trovo davvero stimolante cercare di aiutare altre persone perchè spesso e volentieri questo sforzo è ricompensato con l'imparare o lo scoprire qualcosa di nuovo. E' stato così durante lo slot di stamane durante il quale ho scoperto che una cosa che stavo cercando di spiegare ad una persona, in realtà si sarebbe potuta applicare anche ad una applicazione cui sto lavorando io stesso. E il bello è che prima non mi era nemmeno venuta in mente.

Questo per dire che lo slot di stamane, sebbene faticoso come il precedente è stato decisamente più positivo. Vale sia dal punto di vista meramente tecnologico che da quello della lingua inglese. Alla fine infatti ho totalizzato ben due ore e mezza continuative di conversazione con un simpatico collega spagnolo che con la sua irruenza mi ha praticamente costretto a parlare per tutto il tempo. Oramai credo di poter dire che la barriera linguistica è stata superata...

Le sessioni si stamane sono state molto più positive. Ho seguito inizialmente una sessione a proposito della localizzazione di WPF e Silverlight. Lo speaker m'è sembrato piuttosto preparato e nonostante abbia parlato per la maggior parte del tempo di WPF mi ha dato qualche utile informazione su Silverlight confermando il mio sospetto che il supporto alla localizzazione sia praticamente nullo... e visto l'interesse dell'argomento penso che dedicherò ad esso un intero post non appena tornerò a casa.

Verso la fine della giornata ho deciso di seguire una sessione di su RIA e il . Credo di essere del tutto onesto se dico che vorrei averne capito un po' più del 10%. Mi riprometto di esaminare con calma la questione, di documentarmi e magari postare qualcosa di più preciso. Una cosa è certa, Pat Hellan parla un inglese che pare scritto da tanto è chiaro...

La giornata si è conclusa con un panino al Burger King in compagnia di Andrea Dottor, Davide Vernole e . Come sempre una compagnia affidabile e ilare. Eppoi ora che Alead s'è comprato una Nikon non mi rimane che vantarmene con qualche sfegatato ...

Technorati Tags:

FW106.jpg qualche tempo fa che mi trovavo un po' in crisi per problemi di  tastiera. Alla fine ho trovato una soluzione accettabile ai miei problemi sul sito della DELL. Il tutto è partito dal fatto che la tastiera che uso in ufficio risponde bene alle mie esigenze e quindi, anche grazie ai consigli di un collega, ho provato a vedere sul sito del produttore se ci fosse una tastiera che mi potesse andare bene anche per casa. E in effetti era li in bella mostra che mi aspettava ed era esattamente quello che volevo: la versione wireless della tastiera che ho in ufficio. Un po' più curata esteticamente della versione "base" che viene data assieme ad un nuovo pc, con una scocca in alluminio che la rende più solida e una banda per i polsi in dotazione, con qualche pulsantino in più per i preferiti, il media player etc, ma fondamentalmente la tastiera ideale... e quindi è scattato l'acquisto.

Ragazzi è uno splendore! Finalmente ho il feedback che cercavo, forse anche un po' meglio di quello della versione base, il tutto in una tastiera probabilmente un po' costosa (70 euro) ma nata proprio per le esigenze di chi la usa per lavorare e quindi ci deve passare un sacco di tempo.

Ancora una volta DELL mi ha risolto i problemi... lo stesso non si può dire delle poste che mi hanno perso la prima spedizione. Ma questo è un altro discorso :(

Technorati Tags: ,,

Se come a me vi capita di avere problemi di installazione di Silverlight 2.0 Beta2 vi consiglio di guardarvi questo di Brad Bartz che fornisce molte utili indicazioni per risoverli. Il problema principale che ho riscontrato è che l'installer silverlight_chainer.exe - per intenderci quello che installa tutto il necessario, Tools e SDK compresi - non è stato in grado di rimuovere una patch di Visual Studio 2008 (KB949325). Perciò vi consiglio di verificare a mano nel pannello di controllo che questa patch sia presente e in tal caso di disintallarla prima di lanciare il setup di Silverlight 2.0.

Inoltre, prima di eseguire Visual Studio 2008, subito dopo il termine dell'installazione, ricordate di azzerare i packages eseguando il seguente comando:

devenv /resetskippkgs

Dopo queste operazioni che ho faticosamente estratto dal lungo post, finalmente tutto ha cominciato a funzionare a dovere... almeno spero.

Ecco il link:

UPDATE: Verificate anche quanto riportato in questo post


Poco fa ho quello che ritengo un problema riscontrato in Silverlight 2.0. Quello che avviene è che la classe base della pagine (UserControl) viene dichiarata anche nella parte autogenerata della partial class. Questo fa si che sia impossibile ereditare una pagina da una propria classe base e costringe a scrivere molto codice duplicato.

Speriamo che la venga accolta...

Technorati Tag: ,

Da quando ho iniziato a lavorare con ASP.NET e maggiormente oggi, quando ASP.NET AJAX è ormai prepotentemente entrato nelle mie applicazioni, mi sono spesso scontrato con un problema che credo che molti altri abbiano  riscontrato e affrontato nei modi più disparati. Il problema in questione deriva dalla modalità con cui i server controls di ASP.NET generano gli id degli elementi che poi vengono resi nella pagina. Questi identificatori, che tipicamente corrispondono almeno nella parte finale all'id che viene utilizzato lato server, quando arrivano al client sono spesso arricchiti di informazioni allo scopo di renderli realmente univoci all'interno del DOM html. Mi riferisco a quello che noi tutti conosciamo con il nome di ClientID, che spesso e volentieri ci costringe a generare dei piccoli pezzetti di codice javascript per riuscire ad operare su di essi come segue:

 

var myControl = document.getElementById('<%= myControl.ClientID %>');

Personalmente ho sempre trovato questa operazione stucchevole e inutilmente laboriosa e finalmente, con l'avvento di AJAX e della Microsoft AJAX Library mi sono deciso a metter insieme una serie di idee e a trovare una soluzione dignitosa. La soluzione in realtà riprende ed estende un che ho fatto poco tempo fa. Il principio che allora proposi era quello di creare una sorta di client-codebehind in Javascript che permettesse di incapsulare e in qualche modo meglio organizzare tutto il codice che siamo abituati a scrivere per attivare sul client le nostre pagine. E' stato allora che ho realizzato che tale modello con un passo ulteriore poteva diventare una valida soluzione al problema dei ClientID. Creando infatti una classe base per questo codice e iniettando al suo interno i riferimenti Javascript ai controlli, il modello di programmazione client-side diventa pressochè analogo a quello del server liberandoci così dei voli pindarici cui siamo ormai assuefatti.

Per ottenere questo modello, ho pensato di estendere sua signoria lo ScriptManager. Dato che è proprio di codice di Script che stiamo parlando mi è sembrato il punto naturale per dare vita alla mia soluzione. Inoltre, avendo comunque bisogno di un riferimento alla Microsoft AJAX Library l'uso dello ScriptManager diviene pressochè obbligatorio. Ecco quindi che ho creato un ExtendedScriptManager che cela al suo interno le seguenti cose:

  1. Una collection di ClientReference che consente di specificare quali dei controlli server-side è necessario portare sul client. Questo è dovuto innanzitutto alla scelta di indicare esplicitamente tali controlli per evitare l'inutile proliferazione del codice di script oltre alla necessità di gestire diverse modalità di referenziazione atte a gestire diverse tipologie di controlli e diverse esigenze.
  2. Una proprietà PageClass che indica quale classe istanziare, inserita in un apposito file js referenziarto per rappresentare il codebehind della pagina. Questa classe dovrà estendere la classe Javascript Elite.Page inclusa nell'assembly e referenziata automaticamente dal codice dell'ExtendedScriptManager.

Inoltre ho dovuto estendere anche lo ScriptManagerProxy per mantenere questo tipo di modello anche nei casi in cui si faccia uso di questo controllo. Lo script manager esteso in mancanza di una PageClass si comporta in modo del tutto analogo ad uno ScriptManager classico perciò è possibile usarlo in tutta tranquillità in una masterpage e impostare la PageClass solo nello ExtendedScriptManagerProxy ove ve ne sia la necessità.

L'impostazione della PageClass fa sì che lo ExtendedScriptManager produca qualche riga di codice javascript, legata all'onload dell'applicazione, che si occupa di istanziare la classe specificata e di iniettare al suo interno tutte le ClientReference esplicitate. Ecco un breve esempio di pagina che fa uso del mio modello:

 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Elite.Library.Web.DefaultPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Test Page</title> </head> <body> <form id="form1" runat="server"> <elite:ExtendedScriptManager ID="ScriptManager1" runat="server" PageClass="Elite.DefaultPage"> <ClientScriptReferences> <elite:ClientScriptReference ClientInstanceName="_bTest" TargetControlID="bTest" /> </ClientScriptReferences> <Scripts> <asp:ScriptReference Path="/Default.aspx.js" /> </Scripts> </elite:ExtendedScriptManager> <div> <asp:Button runat="server" ID="bTest" /> </div> </form> </body> </html>

In questa brevissimo pagina si fa uso dell'ExtendedScriptManager per creare una referenza ad un pulsante (bTest) e per istanziare la classe Elite.DefaultPage. A scopo dimostrativo ho volutamente lasciato in biano il pulsante omettendo di valorizzare la proprietà Text per settare questo valore sul client con la data corrente. Ecco il codice della classe:

 

Type.registerNamespace('Elite'); Elite.DefaultPage = function() { Elite.DefaultPage.initializeBase(this); } Elite.DefaultPage.prototype = { load : function() { this._tick$handle = setInterval( Function.createDelegate(this, this._tick), 1000); }, unload : function() { if (this._tick$handle) { clearInterval(this._tick$handle); delete this._tick$handle; } }, _tick : function() { this._bTest.value = new Date(); } } Elite.DefaultPage.registerClass('Elite.DefaultPage', Elite.Page);

In questa classe, realizzata con il Type System della Microsoft AJAX Library si fa uso della referenza introdotta dall'ExtendedScriptManager per valorizzare il testo del pulsante con la data e l'ora corrente, aggiornate ogni 1000 millisecondi. Il codice è banale, ma quello che vorrei evidenziare è la presenza dei metodi load e unload che hanno il medesimo significato degli omonimi eventi server-side. Essi sono completati dai consueti initialize e dispose che derivano da Sys.UI.Control, classe base di Elite.Page. Infine è da nostare anche che il campo membro _bTest non è mai valorizzato; esso infatti viene introdotto dal codice generato dul server:

 

<script type="text/javascript"> //<![CDATA[ Elite.registerServerControls = function(pageInstance, args) { pageInstance._bTest = $get('bTest'); }; Sys.Application.add_init( function() { Elite.Page.Current = $create( Elite.DefaultPage, { }, { beforeLoad : Elite.registerServerControls }, null, window); }); Sys.Application.initialize(); //]]> </script>

In particolare la referenza iniettata nella pageInstance è quella che poi verrà utilizzata dal nostro codice.

Personalmente sto utilizzando questo sistema da un po' di tempo, e al momento posso dirmi soddisfatto perchè finalmente ho trovato il modo di razionalizzare il lavoro e di ricondurlo ad un modello molto simile a quello che ASP.NET ci mette normalmente a disposizione. Mi interessa conoscere anche la vostra opinione perciò ho deciso di condividere con voi questo codice. Spero che qualcuno trovi utile la solzione e mi dia qualche consiglio su come mgliorare ulteriormente la piccola libreria. Il codice è stato scritto sul framework 3.5 e richiede l'uso di Visual Studio 2008.

Download: http://blog.boschin.it/download/Elite.Web.rar

Technorati tags: , , ,

A quanto pare ci sono dei problemi ad includere il nuovo file silverlight.js, introdotto dalla beta 1 all'interno di progetti che contengano uno ScriptManager di ASP.NET AJAX. I problemi devo dire sono intermittenti nel senso che esiste almeno una combinazione di questi elementi che funziona, ma in realtà ancora non sono riuscito a capire esattamente quale. Il problema deriva da una doppia dichiarazione del namespace SYS per cui se includete silverlight.js, ASP.NET AJAX non sarà più in grado di trovare il proprio.

Stamattina ho trovato un sul forum di Silverlight. In buona sostanza pare che il problema si risolva dichiarando il file js all'interno dello ScriptManager stesso:

   1: <asp:ScriptManager ID="sm" runat="server">
   2:     <Scripts>
   3:          <asp:ScriptReference Path="silverlight.js" />
   4:     </Scripts> 
   5: </asp:ScriptManager>

In tutta sincerità la soluzione è piuttosto semplice, ma confesso di non averci pensato. Stasera provo a vedere se è davvero così semplice.

Technorati tags: , , ,

Tempo fa ho accennato al fatto che XAML è uno dei migliori metodi di serializzazione che siano mai stati inventati. Tuttavia negli ultimi giorni ho avuto qualche delusione di troppo, che non ha variato la mia opinione in merito, ma semplicemente ha ridotto la mia fiducia nell'implementazione corrente. Il problema peggiore è dovuto ad una limitazione, per la verità esplicitata nella documentazione, che però crea più grattacapi del previsto. Se ad esempio provare a serializzare con XamlWriter un oggetto che contiene una stringa vuota vi troverete con uno XAML risultante che XamlReader non sarà in grado di riportare alla vita... Il problema come dicevo appare ovvio dopo che si è letta la documentazione. XamlReader non è in grado di deserializzare tipi che non abbiano un costruttore di default. A ben guardare il tipo String tale costruttore non lo ha proprio e l'effetto collaterale è che quando XamlReader tenta di deserializzare una stringa che abbia un valore tutto va bene, mentre ovviamente va in eccezione quando la stringa è vuota.

Comunque, per chi desidera cimentarsi, ecco un utile link dove si discute di XamlWriter

Link: http://blogs.msdn.com/mikehillberg/archive/2006/09...


Nel pomeriggio ho seguito la sessione fiume di Andrea Saltarello. Come al solito da Andrea non ci si può aspettare altro che il reale succo delle questioni, spiegato in modo molto efficace. Nonostante si trattasse anche in questo caso di concetti che per la gran parte avevo già abbastanza chiari, qualcosa da imparare c'è sempre. In particolare un accenno di Andrea alla sua sessione di Venerdì mattina mi ha fatto intuire che alcune cose che recentemente ho considerato tra me e me ma che ancora non ho palesato, non sono del tutto infondate. Mi riferisco al fatto che Object Oriented Programming e Service Oriented Architecture fanno un po' a pugni. Provate a pensare ad esempio ad un oggetto di tipo Order, con una proprietà Details di tipo IList<OrderDetail>.  In un domino OOP puro, gestito con un mapper relazionale come ad esempio NHibernate la proprietà Details dovrebbe godere dell'uso di un pattern LazyLoad per fare in modo che i dettagli dell'ordine vengano caricati solo alla bisogna. Questo vale però solo esclusivamente quando rimaniamo all'interno di un AppDomain che possa in qualche modo persistere la sessione, perchè non appena usciamo dall'AppDomain, come avviene ad esempio se l'oggetto viene erogato da un WebService, il lazy load non può più esistere, o meglio, non possiamo fare affidamento su NHibernate per questo, ma dobbiamo arrangiarci a mano. Per quanto mi riguarda, per ora ho trovato la soluzione più agevole nello esplicitare i metodi del WebService ed esporre negli oggetti del dominio gli ID che collegano le entità. Così nel caso di esempio avremo un oggetto Order che porta semplicemente le proprietà semplice, di quanlunque tipo esse siano e poi ci saranno rispettivamente i metodi

public Order GetOrder(int id);

public IList<OrderDetail> GetOrderDetails(Order order);

Naturalmente si tratta di una semplificazione, al solo scopo di chiarire il mio pensiero, ma credo che sia abbastanza aderente alla realtà. Al momento, pur avendo altre idee per la testa che coinvolgono l'uso di  partial classes e cose del genere, trovo ancora più pulito ed essenziale questo approccio. Sentiremo Venerdì se sarò confermato o smentito.


Pare proprio che "Cider", che altri non è che il nome in codice per le estensioni WPF per Visual Studio 2005, sia rimasto un passo indietro rispetto a WPF stesso. All'uscita del Framework 3.0 di ieri infatti non è corrisposta l'uscita della versione definitiva di questo importante componente. La CTP di Novembre, che ieri si è accompagnata alla RTM del Framework nei vari link che si sono trovati in giro infatti soffre di qualche problema, il primo di tutti quello che impedisce di dichiarare namespace custom all'interno di file XAML. Semplicemente il farlo è indispensabile, ma fa scoppiare il designer e qualche volta anche l'intellisense. Sinceramente speravo che con l'uscita della release definitiva di Windows Presentation Foundation si riuscisse a dare uno strumento per usarla in modo produttivo, ma con Expression ancora in beta e "Cider" in CTP temo dovremmo ancora attendere molto.


Lo scorso 11 ottobre Microsoft ha rilasciato una patch per alcuni problemi di sicurezza riscontrati in Internet Explorer. A quanto pare tale patch crea più problemi che benefici perchè la sua applicazione causa evidenti malfunzionamenti nello stesso browser ma anche nello snap-in della Microsoft Management Console che riguarda i servizi e nell'applet di gestione utenti del pannello di controllo. Finalmente oggi, spinto da reale necessità che il mio browser tornasse a visualizzare gli ActiveX ho scoperto la soluzione che trovate al seguente indirizzo accompagnata da una esaustiva descrizione del problema.

Link: http://windowsxp.mvps.org/olereg.htm

powered by IMHO 1.3


Ho appena completato l'upload del package di installazione corretto per la versione 1.3.2106. Il problema segnalato da Simone Busoli e Andrea Dottor risiedeva appunto nell'aver indicato la versione 1.2.2106 nel file AssemblyInfo, e aver poi scritto ovunque 1.3.2106. Questo causava l'apparizione del numero di versione errato nell'AboutBox che appunto lo legge direttamente dai metadata dell'assembly, e dalla apparizione "incomprensibile" del balloon che informava sulla presenza di una versione più nuova online, nonostante la si fosse appena installata. Ora tutto è a posto. Buon divertimento.

powered by IMHO 1.3