Messaggio di errore Ambiguous match found e httpParseException

Scenario: web application che utilizza la versione 1.1 di ASP .NET migrata direttamente alla versione 3.5. Dopo la migrazione su una delle pagine ASPX viene sollevato una HttpParseException durante il caricamento della stessa. L’eccezione in questione, come si evince dal nome, viene generata dal runtime di ASP .NET quando il parsing di una pagina ASPX fallisce a runtime. Il messaggio di errore recita “Ambiguous match found”, e quindi non aiuta granchè. La cosa curiosa è che l’eccezione non si verifica in ambiente di sviluppo ma solo sulla versione di deploying dell’applicazione, quindi non è “debuggabile” in Visual Studio 2008 ( a meno di non effettuare un debug in remoto, cosa quasi mai possibile in ambiente di produzione) , e quindi non è di facile risoluzione.

In questi casi la prima cosa che penso è: sicuramente altri developers sparsi per il mondo hanno già sperimentato lo stesso problema, quindi  mi metto a perlustrare blogs e forum e normalmente alla fine il problema si risolve !

E così è stato anche stavolta, anche se le cause di questa eccezione possono essere diverse e quindi non esiste una soluzione universalmente applicabile.

Alcune delle cause che possono produrre una httpParseException sono, in ordine sparso:

  1. la pagina contiene un campo hidden che ha un ID con lo stesso nome di una variabile querystring usata dalla stessa pagina;
  2. la pagina ha un controllo (non ascx) inserito nel file ASPX (e quindi inserito nella partial class non visibile), e nel code-behind della stessa è dichiarato un altro controllo protected con lo stesso nome;
  3. la pagina contiene un controllo ASCX con lo stesso nome di un controllo nativo ASP .NET;

Tutte queste situazioni generano evidentemente una ambiguità dei tipi, che porta all’eccezione.

Inoltre,  effettuando un deploy del sito con l’opzione “non aggiornabile”, ovvero deselezionando l’opzione “Allow this precompiled site to be updateable”, l’eccezione dovrebbe scomparire, salvo poi approfondire le sue cause e riabilitare nel caso l’opzione.

Partial rendering troubleshooting

Regola importante: l’update parziale di una pagina ASP .NET 2.0 (o successivi) attraverso l’UpdatePanel di Ajax non funziona in presenza di questo tag nel file di configurazione dell’applicazione (o nel machine.config):

Infatti, con questa impostazione la proprietà “SupportPartialRendering” dell’oggetto ScriptManager ritorna il valore false.

Il tag in questione imposta la modalità di rendering dei controlli, es.:  in modalità compatibile XHTML (mode=”Transitional” o “Strict”) oppure no (mode=”Legacy”).

In ASP .NET 1.1 i controlli subivano un rendering non XHTML compatibile, e questo comportamento è stato modificato in ASP .NET 2.0, che invece effettua il rendering XHTML compliant. Questo significa che se si migra una applicazione scritta con la versione 1.1 del .NET Framework ad una versione più recente, il wizard di migrazione imposta l’xhtml conformance mode in modalità Legacy, provocando di fatto il mancato funzionamento del partial rendering. Per risolvere il problema è sufficiente impostare il tag mode a “Transitional” (valore di default) oppure “Strict”, oppure rimuovere il nodo in modo tale da assegnargli il valore  di default, es.:

Opportunità di lavoro

Interessante opportunità di lavoro su Milano:

importante azienda cerca programmatore/programmatrice senior C# con buona conoscenza .NET Framework, ASP .NET e Oracle.

Offresi contratto di assunzione e/o di consulenza.

Titolo preferenziale: conoscenza del .Framework 3.5 e di C# 3.0.

Le persone eventualmente interessate possono contattarmi attraverso la form contact di questo blog.

TextBox ReadOnly in .NET 2.0 e successivi

Il controllo TextBox di una web application dispone della proprietà ReadOnly che, ovviamente, impedisce l’interazione dell’utente con il controllo quando è impostata a True.

Ma c’è un particolare importantissimo da considerare: a partire dalla versione 2.0 del .NET Framework il contenuto di un textbox in modalità “ReadOnly” è inviato al server durante un postback della pagina, ma il server ignora questo valore; in altre parole il contenuto del textbox viene perso durante un postback. Questo comportamento mira ad impedire attacchi alla sicurezza, che potrebbero modificare un valore che dovrebbe essere mantenuto inalterato.

La perdita del valore del textbox può essere inaccettabile in certi contesti applicativi e potrebbe essere necessario applicare il comportamento in essere prima del Framework 2.0. Per far ciò è necessario impostare la proprietà ReadOnly come attributo del controllo, in questo modo:

TextBox1.Attributes.Add("readonly","readonly")

e non impostando a True la relativa proprietà.

Così facendo il valore del textbox (ovvero la sua proprietà Text) viene inviato al server durante il postback ed è altresì disponibile per l’elaborazione.

UPDATE: questo aggiornamento è, diciamo così, dovuto: il “copyright” di questa scoperta che ha portato via parecchio tempo prima di venirne a capo non è mio ma della mia collega di lavoro Ines. Io ho solo raccolto il troubleshooting per aiutare altri programmatori come un tempo altri programmatori hanno aiutato me

Sottili differenze tra C# e VB .NET #Part 2#

Questa informazione me la annoto perchè sicuramente utile. Avevo già parlato precedentemente delle sottili e a volte subdole differenze esistenti tra il linguaggio VB .NET  e C#, differenze che possono anche riguardare il comportamento di Visual Studio, quindi non strettamente legate a costrutti di programmazione o alla semplice sintassi.

Questa differenza però mi sorprende parecchio e non riesco a comprenderne a fondo il motivo. Presto detto: se si utilizza l’incremento automatico nel numero di versione in un assembly (per intenderci quando impostiamo questa riga

[assembly: AssemblyVersion("1.0.*")]

nel file AssemblyInfo, otteniamo un risultato differente a seconda se l’assembly è scritto in VB .NET o in C#. Se è scritto in VB .NET l’incremento automatico è operato solo alla prima build, mentre alle successive build sulla stessa istanza di Visual Studio il numero di versione resta invariato (se l’assembly viene ricompilato in una differente istanza di Visual Studio il numero di versione è incrementato).

Se, viceversa, l’assembly è scritto in C#, ogni build produce un incremento automatico del numero di versione. Appena mi è possibile proverò questa funzionalità, anche se la documentazione MSDN è abbastanza chiara.

Questo comportamento differente in funzione del linguaggio avrà anche una sua logica, ma non è sicuramente immediatamente chiara.

Inoltre, non condivido la motivazione che la documentazione MSDN produce per spiegare il tutto: poichè il numero di versione è inserito solo a titolo informativo in un assembly non firmato con uno strong name, il problema non si pone. Viceversa, se l’assembly deve essere dotato di strong name, viene sconsigliato l’uso dell’incremento automatico, in VB .NET chiaramente, perchè in C# non c’è alcuna controindicazione.

Nuovo feed

Come già comunicato qui ho deciso di spostare il feed del mio blog su FeedBurner, un ottimo servizio esterno che consente tra l’altro di ottenere gratuitamente servizi aggiuntivi, e soprattutto di svincolare il proprio blog dal proprio feed rss “interno”, permettendo quindi di centralizzarlo con indubbi benefici, es. la possibilità di pubblicare i propri contenuti anche su altri blogs.

Chi volesse sottoscrivere il mio blog dovrà dunque utilizzare il nuovo feed disponibile all’url: http://feeds.feedburner.com/mauriziotammacco

Impostare la scheda LAN con file batch

Non sono un sistemista, nè lo saro mai, ma anche occupandosi solo di sviluppo è utile avere sottomano tools e/o tips prettamente sistemistici che possono essere sicuramente utili.

Eccone uno:

1) netsh interface ip set address “Connessione alla rete locale (LAN)” static 10.xxx.xxx.xxx 255.255.255.0 10.xxx.xxx.xxx 0
2) netsh interface ip set dns “Connessione alla rete locale (LAN) ” static 10.xxx.xxx.xxx primary
3) netsh interface ip add dns “Connessione alla rete locale (LAN)” 10.xxx.xxx.xxx
4) netsh interface ip show config “Connessione alla rete locale (LAN) “

I comandi sopraelencati, messi opportunamente in un file .bat, permettono di settare al volo la configurazione di una scheda di rete ben precisa, ovvero quella la cui descrizione è “Connessione alla rete locale (LAN)”, nell’esempio.

Ovviamente basta cambiare la descrizione della scheda per puntarne un’altra.

La prima riga del batch setta rispettivamente l’indirizzo ip, la subnetmask ed il default gateway. La seconda riga imposta l’indirizzo ip del server dns primario, mentre la terza quello del dns secondario. La quarta riga visualizza a console le impostazioni della scheda appena settate.

Questo vale quando vogliamo settare indirizzi ip ben specifici. E se invece vogliamo che la scheda sia impostata con indirizzi ip ottenuti da un server DHCP ?

Ecco i comandi:

1) netsh interface ip set address “Connessione alla rete locale (LAN)” dhcp
2) netsh interface ip set dns name=”Connessione alla rete locale (LAN)” source=dhcp
3) netsh interface ip show config “Connessione alla rete locale (LAN)”

Per la descrizione della scheda vale quanto già detto. La prima riga imposta la modalità DHCP. La seconda imposta la modalità DHCP per i server DNS, mentre la terza mostra a console la nuova configurazione.

FeedBurner e CommunityServer

Finalmente ho trovato il tempo per aggiornare la versione di Community Server con cui gira questo blog; ho infatti effettuato un aggiornamento “doppio” passando dalla versione 1.1 alla versione 2007.1. L’aggiornamento era d’obbligo per via delle nuove feature della versione 2007. Ma non è stato semplice, anche per via della connessione Internet a mia disposizione (una lentissima UMTS).

A proposito, questo è l’ultimo post scaricabile attraverso il consueto rss feed; ho deciso infatti di usufruire del servizio messo a disposizione da FeedBurner, un servizio esterno che eroga feed rss,  fornendo nel contempo altri utili servizi.  Nel prossimo post comunicherò il nuov url da cui è possibile sottoscrivere questo blog. 

Eccezioni non gestite in ASP .NET 2.0

Le eccezioni non gestite generate da una applicazione ASP .NET compilata con la versione 2.0 del .NET Framework sono trattate diversamente da quanto avveniva con le applicazioni ASP .NET compilate con la versione 1.0/1.1. Queste ultime semplicemente ignoravano le eccezioni non gestite sollevate all’esterno del contesto corrente, es. un thread diverso da quello principale, mentre le eccezioni sollevate all’interno del contesto erano trattate normalmente come qualsiasi eccezione non gestita. Con il .NET Framework 2.0 questo comportamento è cambiato: le eccezioni non gestite sollevate fuori dal contesto provocano l’immediata interruzione del worker process e conseguentemente dell’applicazione. L’unica traccia è un laconico messaggio nell’event viewer  (System Log) del tipo “DefaultAppPool terminated unexpected”, seguito da un ancor più generico messaggio nell’Application Log (Event Source: .NET Runtine 2.0 Error Reporting).

Ma questo comportamento (il default) è legato ad una precisa policy di gestione delle eccezioni non gestite e può essere modificato in 2 modi:

-Aggiungendo le seguenti righe nel file Aspnet.config:

per fare in modo che le eccezioni non gestite siano trattate come nel .NET Framework 1.0/1.1, ovvero ignorate (scelta non
raccomandata da Microsoft)

-Creando un opportuno httpModule che si registra per l’evento AppDomain.CurrentDomain.Unhandledexception, attraverso il quale loggare i dettagli dell’eccezione  non gestita verificatasi.

Il tutto è documentato in questo articolo, con un esempio di httpModule.

Shortcut CTRL+K+F e CTRL+K+D

Questo shortcut è davvero utilissimo: CTRL+K+F premuto all’interno di Visual Studio con attiva una finestra di editor del codice sorgente. Selezionando una regione di codice non formattato, non allineato o non indentato correttamente (tipicamente derivante da un precedente copia e incolla), questa combinazione allinea perfettamente le righe di codice in un colpo solo !

Fonte: Mark Schmidt’s Abode

P.S: Nel commento al post linkato, leggo che la combinazione CTRL+K+D effettua la stessa formattazione delle righe ma agendo sull’intero file e non solo sulla selezione di testo. Spettacolo!

Metriche del codice e SourceMonitor

Ho provato SourceMonitor, un interessante tool freeware per effettuare metriche sul codice sorgente scritto in vari linguaggi di programmazione, tra cui C#, C, C++, VB .NET, Delphi.

Attraverso una interfaccia di gestione molto semplice acquisisce una serie di informazioni, le metriche appunto, analizzando il codice sorgente di un progetto. Queste informazioni possono essere salvate in diversi momenti e nominate (checkpoints), onde poter mettere a confronto metriche di uno stesso progetto create in momenti diversi.

Analizzare le metriche del proprio codice aiuta ad evidenziare eventuali colli di bottiglia, ovvero parti dello stesso da sottoporre a code review, e a migliorare quindi la qualità del codice scritto.

Ecco un elenco delle metriche a mio avviso più importanti:

-% delle linee di codice commentate rispetto al totale delle linee di codice presenti in un file;
-Numero delle classi, interfacce o strutture definite in un file;
-Numero medio di metodi per classe, interfaccia o struttura;
-Valore di complessità per tutti i metodi, ovvero numero totale dei diversi percorsi di esecuzione che ogni metodo  possiede (maggiore è questo valore, più “complesso” è il metodo). Questo valore si puo’ ottenere sia per singolo  metodo, sia come media della complessità di tutti i metodi presenti.

Come detto, analizzare le metriche del codice può aiutare a scrivere codice di qualità, e quindi ad essere uno sviluppatore migliore.

Evento One-Day web development

Per tutti gli sviluppatori ed architect in ambito Web questo evento è assolutamente imperdibile. One-Day web development, organizzato dalla community XE.Net (una delle mie preferite), si propone sia di illustrare la roadmap Microsoft in relazione al presente ed al futuro dello sviluppo nel mondo web, sia di mostrare all’opera Silverlight unito ad AJAX e LINQ, ovvero strumenti che rivoluzionano la user experience di una web application rendendola analoga ad una applicazione WinForm.

Ugialt.net

Prendo a prestito delle parole di Antonio Carpentieri per descrivere il perchè ho aderito con entusiasmo all’iniziativa ugialt.net:

“…..Ha un mix di agile + object-orientation + patterns + TDD + DDD. Perchè per ognuno dei punti di cui sopra esistono degli strumenti che permettono di applicarli in .net, perchè li USO, perchè spesso ho dei dubbi, delle perplessità ma nonostante queste effettuo delle scelte sia di design, che di processo e VOGLIO informarmi su come altri stanno lavorando, fanno evolvere i pattern di design o del processo perchè cerco il modo migliore di comunicare e motivare delle scelte tecniche che agli occhi di un manager che vede solo “the microsoft way” possono risultare solo le scelte di un geek… ecco, io mi sento a casa in mezzo a persone che hanno questo spirito. Condividere per crescere. Creare senza aspettare.”

Implementazione esplicita di membri di interfaccia

L’implementazione esplicita di una interfaccia presenta caratteristiche significative rispetto ad una implementazione per così dire non esplicita. Ad esempio, si consideri l’interfaccia:

public interface IExplicitImplementation 
{ 
   string Method1(string par); 
}

e la seguente classe che la implementa in modo esplicito:

public class Class1 : IExplicitImplementation  
{
    string IExplicitImplementation.Method1(string par) 
    {
       return “Hello world “ + par;
    }
}

Le caratteristiche salienti sono:

– Il client che consuma la classe Class1 utilizzando una istanza di quest’ultima è impossibilitato a richiamare il metodo Method1 in quanto quest’ultimo NON fa parte dell’interfaccia pubblica della classe (non è visibile con l’intellisense ed il tentativo di richiamare comunque il metodo genera un errore di compilazione).

Questo codice genera un errore di compilazione:

Class1  cl1 = new Class1();
cl1.Method1();

– Il client che consuma la classe Class1 può invocare il metodo Method1 solo attraverso una istanza dell’interfaccia IExplicitImplementation che la classe stessa implementa esplicitamente. Vale a dire:

ExplicitImplementation i = new Class1();
Console.WriteLine( i.Method1(“Maurizio”));

Quindi un metodo che implementa esplicitamente una interfaccia è, per così dire, privato e pubblico nello stesso tempo. E’ privato perchè non compare nell’interfaccia pubblica della classe e non può essere richiamato attraverso una  istanza della classe stessa; è pubblico perchè può comunque essere richiamato utilizzando una istanza dell’interfaccia.

– Un metodo che implementa esplicitamente un membro di una interfaccia non può contenere alcun modificatore di accesso, nè i modificatori static, abstract, override e virtual. L’ultima caratteristica determina anche l’impossibilità di effettuare l’override di una implementazione esplicita di un membro di una interfaccia. Questo ostacolo è comunque raggirabile dichiarando un altro metodo virtuale (e quindi ridefinibile) e richiamando quest’ultimo metodo nel codice che implementa esplicitamente un membro di una interfaccia.

Come terminare un processo corrotto in .NET

Da .NET 2.0 in poi è possibile terminare un processo corrotto irreparabilmente attraverso il medodo Environment.Failfast(string message), il quale provvede a:

  1. Scrivere una entry nell’Application Event Log con il messaggio specificato
  2. NON eseguire alcun blocco try-finally ancora in sospeso
  3. NON esegue alcun finalizer sugli oggetti ancora in memoria
  4. Esegue un dump dell’applicazione
  5. Termina il processo

I punti 2-3 sono necessari in un contesto simile in quanto la loro esecuzione potrebbe danneggiare risorse usate dall’applicazione stessa. Tuttavia gli oggetti CriticalFinalizerObject (di cui magari parlerò in un post a parte) sono comunque eseguiti prima di terminare il processo.

Inconsistenza operatori di confronto dei Nullable Types in C#

Il linguaggio C# offre un supporto decisamente migliore dei Nullable Types rispetto a VB .NET. Nonostante ciò, utilizzando gli operatori di confronto su un tipo Nullable, es. un intero, il risultato è a dir poco strano e può dar luogo a bug piuttosto subdoli.
Infatti, eseguendo il seguente codice:

int? a;
int? b;
a=null;
b=null;
Debug.WriteLine(a == b);
Debug.WriteLine(a != b);

l’uguaglianza dei due tipi nullable con entrambe le variabili impostate a null dà come risultato “true”, mentre  l’operatore  di disuguaglianza  sulle stesse variabili produce come risultato “false”. Sin qui il comportamento è coerente.

Questo codice invece:

produce in entrambi i casi un risultato pari a "false", risultato a prima vista strano, oserei quasi dire illogico.

In sostanza:

  • "a" è uguale a "b", ma "a" non è maggiore "oppure" uguale a "b".
  • "a" è uguale a "b", ma "a" non è minore "oppure" uguale a "b"

I commenti sono aperti.

Troubleshooting remote assistance

Per una volta parlo di come risolvere un piccolo ma noioso problema sistemistico: provando ad utilizzare l’assistenza remota di MSN mi appariva questo strano errore:

“Impossibile aprire la Guida in linea e supporto tecnico perchè un servizio di sistema non è in esecuzione. Per risolvere il problema, avviare il servizio denominato ‘Help Service”

Il servizio in questione, chiamato “Guida in linea e supporto tecnico” nella versione italiana, è chiaramente la Guida in linea di Windows XP, che evidentemente non era presente sulla macchina. Ma l’aspetto più imbarazzante era che non  vi era nessun  servizio chiamato in quel modo tra l’elenco dei servizi di Windows.  Quindi, come  (re)installare la Guida  in linea ?  In questi casi, come al solito, non esiste aiuto migliore dei gruppi di discussione sull’argomento specifico.

Ecco come procedere:

  • Browse della directory c:\windows\inf e cercare il file pchealth.inf. Click destro e scegliere installa.
  • Al temine, installare il servizio attraverso questo comando: Start /w helpsvc /svchost netsvcs /regserver /install 
  • Al termine dell’installazione riavviare Windows XP,  ed ecco che magicamente comparirà il servizio in questione tra i servizi di Windows

Con il servizio avviato, l’assistenza remota di Windows non dà più problemi.

Ora mi chiedo: cosa c’entra la guida in linea di Windows con l’assistenza remota. ?

P.S: Un grazie a Rossano Orlandini, MVP Windows Server, per la soluzione al problema.

XML Serializer Generator Tool

La serializzazione XML in .NET è una operazione onerosa in termini di risorse di sistema a causa della creazione a runtime di un assembly temporaneo contenente funzionalità fortemente tipizzate di “reader” e “writer” del tipo da serializzare, le quali comportano un utilizzo intensivo di CodeDom e Reflection. Osservando con il tool Reflector il codice del costruttore della classe XmlSerializer (comprendente vari overloads) è possibile notare tutto ciò unito all’utilizzo del meccanismo di caching dell’assembly temporaneo creato (sembra però che non tutti gli overloads del costruttore facciano uso della cache con conseguente creazione dell’assembly ad ogni utilizzo). Questo meccanismo è poco performante sia a causa dell’utilizzo delle classi di CodeDom e Reflection, sia per il rischio di creare più assembly temporanei in funzione del numero di classi da serializzare, che resterebbero in memoria fino allo scaricamento del relativo AppDomain o fino a che non termina il processo. Tutto ciò si riflette negativamente soprattutto sulle applicazioni lato server, ed a lungo andare potrebbe provocare eccezioni fatali, es. una OutOfMemoryException. Per ovviare a questo inconveniente il .NET Framework mette a disposizione il tool a riga di comando SGEN (XML Serializer Generator Tool), il quale, lanciato sull’assembly che contiene i tipi da serializzare, genera un nuovo assembly contenente lo stesso codice che verrebbe generato a runtime con la creazione dell’assembly temporaneo. In definitiva è anticipata la creazione dell’assembly, in questo caso non più temporaneo ma definitivo, poichè basta aggiungere un riferimento ad esso, evitando quindi l’overhead della sua creazione a runtime ed eliminando il rischio di crescita incontrollata delle dimensioni dell’AppDomain.

Tra le opzioni del comando SGEN:

-/compiler permette di aggiungere qualsiasi opzione da passare al compilatore C#. Utile per firmare con strong name l’assembly da generare.

-/keep permette di eliminare la cancellazione dei files sorgenti dell’assembly generato. In altre parole lascia i files sorgenti a disposizione dello sviluppatore

-/proxytypes genera il codice di serializzazione solo per i tipi proxy di un XML Web Service

-/reference permette di specificare eventuali assembly referenziati dalle classi oggetto di serializzazione

-/type permette di filtrare i tipi da serializzare che si vogliono includere nell’assembly da generare

Il comando crea un assembly dal nome <proprio assembly>.XlmSerializers.dll che è possibile aggiungere come riferimento alla propria applicazione.

Naturalmente qualsiasi aggiunta/cancellazione/modifica ai membri pubblici della classe da serializzare necessiterà della ricreazione dell’assembly attraverso il comando SGEN (la serializzazione XML serializza solo i campi pubblici di una classe, a differenza della serializzazione standard, binaria o SOAP,  che invece serializza anche i campi privati).

Versione .NET Compact Framework

Per una volta parlo di Windows Mobile, con un piccolo ma credo utile tip:

Per conoscere la versione del .NET Compact Framework installata su un PPC è possibile eseguire una piccola utility chiamata CGACUTIL reperibile nella directory Windows del dispositivo, che visualizza una message box con la versione del .NET Compact Framework installata.