.net comments edit

Appena si crea una nuova Web Application con Visual Studio 2010 la prima cosa che salta all’occhio è l’icona a forma di triangolo posta accanto al web.config, che fa intuire la presenza di alcune voci legate allo stesso; di fatto l’immagine seguente mostra altri due files di configurazione oltre a quello principale:

001

Per noi sviluppatori i files di configurazione rappresentano sempre una parte un po’ ostica, in quanto portano via tempo nella preparazione tra i diversi ambienti con cui siamo “costretti” a lavorare quotidianamente. Normalmente un’applicazione web vive su tre ambienti ben distinti, dove ognuno di questi avrà differenti stringhe di connessione e diversi parametri:

  • Ambiente di sviluppo;
  • Ambiente di test;
  • Ambiente di produzione;

Ovviamente questo numero può variare da applicazione ad applicazione, ma resta il fatto che ad ogni deploy è necessario cambiare la configurazione; oltre ciò, se i files di configurazione in questione sono particolarmente corposi e complessi si aggiunge anche un costo di gestione non indifferente, aumentando inoltre il rischio di errori.
Per capire meglio uno scenario come quello descritto precedentemente, si provi ad immaginare un file di configurazione di un’applicazione web che ha centinaia di parametri, custom section, endpoint, stringhe di connessione, ecc: è pazzesco modificare manualmente ogni file di configurazione.

Fortunatamente con questa nuova release ci viene offerta la possibilità di rendere indolore la gestione di più ambienti grazie all’XDT (Xml Data Trasformation)  ma, per capire bene come sfruttarla, è necessario capire a cosa servono i differenti files e dove andare ad inserire le nostre informazioni.

Il file web.config, quello classico per intenderci, conterrà tutte le informazioni necessarie alla costruzione della configurazione finale, sia che queste informazioni siano uguali per tutti gli ambienti sia che debbano variare.

Sotto il web.config sono presenti due files, Web.Debug.config e Web.Release.config, che hanno il compito di contenere le informazioni che cambiano da ambiente ad ambiente; normalmente i due files creati dovrebbero corrispondere all’ambiente di sviluppo e all’ambiente di produzione, rispettivamente Debug e Release, ma è possibile specificare altri ambienti in base alle proprie esigenze tramite apposite voci, come mostrato dalla sequenza sottostante:

002 003 004 005 006

Nell’esempio seguente verrà mostrato un file di configurazione la cui stringa di connessione è differente tra i tre ambienti, Debug, Release e Test.

Come prima cosa è necessario aggiungere al file web.config l’apposita voce nella sezione connectionStrings, come mostrato di seguito:


  

La stringa presente in questo file coincide con quella dell’ambiente di debug e verrà sostituita da Visual Studio in fase di deploy ma, per far ciò, è necessario andare ad inserire il valore corretto nei restanti files di configurazione, come mostrato di seguito:

    

  


    

    



    

    

Il codice è piuttosto semplice, sono presenti due nuovi attributi xdt:Transform e xdt:Locator, dove xdt significa Xml Data Trasformation;  il primo attributo indica cosa deve essere sostituito (in questo esempio tutti gli attributi), mentre il secondo indica la regola di Matching (in questo esempio il replace viene effettuato nel caso in cui l’attributo “name” coincida tra i files di configurazione).

Ovviamente il numero di operazioni e condizioni disponibili va ben oltre il SetAttributes ed il Match; si ha infatti a disposizione un ricco set di operatori e trasformazioni che permettono di effettuare operazioni piuttosto complesse. Di seguito l’elenco degli operatori ed operazioni utilizzabili:

Operatori:

  • Match – indica che la trasformazione avviene soltanto quando l’attributo inserito all’interno dell’operatore coincide, come mostrato nel nostro esempio;
  • Condition – molto simile alla condizione if, viene utilizzato per specificare i casi in cui la trasformazione deve avvenire (es: xdt:Locator="Condition(@name=’Northwind or @providerName=' System.Data.SqlClient')" );
  • XPath – la sezione da trasformare viene identificata tramite una query XPath(es: xdt:Transform="Replace" xdt:Locator="XPath(//system.web)");

Trasformazioni diponibili:

Replace Effettua il replace dell’intero nodo

<assemblies xdt:transform="Replace">
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"> </add>
</assemblies>

Remove Rimuove il nodo dal file di configurazione corrente

<assemblies xdt:transform="Remove"></assemblies>

RemoveAll Rimuove tutti i nodi all’interno della sezione

<connectionstrings>
<add xdt:transform="RemoveAll"> </add>
</connectionstrings>

Insert Aggiunge un nuovo elemento alla sezione

<authorization>
<deny users="*" xdt:transform="Insert"></deny>
</authorization>

SetAttributes Reimposta gli attributi specificati tra parentesi, separati dalla virgola; in caso di omissione degli attributi vengono sostituiti tutti.

<compilation batch="false"  xdt:Transform="SetAttributes(batch)"> </compilation>

RemoveAttributes Rimuove gli attributi specificati tra parentesi, separati dalla virgola; in caso di omissione degli attributi vengono rimossi tutti.

<compilation xdt:transform="RemoveAttributes(debug,batch)"> </compilation>

InsertAfter Inserisce l’elemento dopo di un altro elemento tramite l’utilizzo di XPath;

InsertBefore Inserisce l’elemento prima di un altro elemento tramite l’utilizzo di XPath;

<authorization>
<allow roles=" Admins" xdt:transform="InsertBefore(/configuration/system.web/authorization/ deny[@users='*'])"></allow>
</authorization>

XSLT Effettua la trasformazione tramite un file XSLT

<appsettings xdt:transform="XSLT(V:\MyProject\appSettings.xslt)"></appsettings>

Per poter provare la trasformazione è necessario effettuare un deploy dell’applicazione cambiando l’ambiente di destinazione, come mostrato dalla sequenza seguente:

007 008 009 010 011

Devo ammettere che l’idea è fantastica e ben implementata, l’unico neo che ho trovato è che, in fase di debug tramite Visual Studio, cambiando l’ambiente di stage tramite l'apposito menu a tendina,  non viene effettuata la trasformazione mandando in play l’applicazione, e questo riduce il raggio di utilizzo della trasformazione alla singola fase di deploy.

Enjoy VS2010!

silverlight comments edit

Ultimamente sto lavorando ad una piccola applicazione in Silverlight, nello specifico un wall di DeepZoom che ha il compito di mostrare le immagini caricate dagli utenti, sfruttando questa fantastica tecnologia.
L’applicazione offre sì la possibilità di caricare le foto direttamente dagli utenti di una community, ma offre anche la possibilità di creare il wall lato editoriale, quindi da backoffice dell’applicativo, e di far ridistribuire sui clients soltanto l’object tag ed il javascript necessario.

Proprio per questo tipo di richieste si può avere la necessità di aggiungere dei parametri custom all’object che si rilascia, in modo che fornisca alcune informazioni utili alla visualizzazione.

In pratica è sufficiente aggiungere un parametro, il cui name sarà initParams, nel tag object della pagina, con al suo interno la coppia chiave-valore che si desidera utilizzare in Silverlight, separati dalla virgola.
L’esempio seguente mostra il markup dell’object.

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
    <param name="source" value="ClientBin/MyApplication.xap" />
    <param name="onError" value="onSilverlightError" />
    <param name="background" value="white" />
    <param name="minRuntimeVersion" value="3.0.40624.0" />
    <param name="autoUpgrade" value="true" />
    <param name="initParams" value="param=1,param2=prova" />
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration: none">
        <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none" />
    </a>
</object>

Lato server, all’avvio dell’applicazione viene effettuato uno split dei vari elementi ed vengono forniti tramite un dictionary nel metodo Application_Startup della classe App del progetto Silverlight.
Il codice seguente mostra come recuperare i valori inseriti nell’object e passarli alla nostra “Page”.

public partial class App : Application
    {
    
        public App()
        {
            Startup += Application_Startup;
            Exit += Application_Exit;
            UnhandledException += Application_UnhandledException;

            InitializeComponent();
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            int parameter1= 0;
            string parameter2 = string.Empty;
            
            if (e.InitParams != null && e.InitParams.Count > 0)
            {
                parameter1= int.Parse(e.InitParams["param1"]);
                parameter2 = e.InitParams["param2"];
            }

            RootVisual = new MainPage(parameter1, parameter2);
        }

        private void Application_Exit(object sender, EventArgs e)
        {
        }
}

Enjoy Silverlight!

.net comments edit

L’utilizzo del Parallel Programming in .NET 4.0 va oltre a quanto già detto qui: di fatto all’interno del namespace System.Threading.Tasks esiste una classe Parallel che permette di effettuare cicli sfruttando più Threads, in modo da abbassare il tempo necessario all’iterazione.

Lo snippet seguente mostra un semplicissimo ciclo di 50 elementi con e senza il Parallel For, con risultati nettamente a vantaggio dell’istruzione Parallel.For.

static void Main(string[] args)
{
    Console.WriteLine("MTID={0}", Thread.CurrentThread.ManagedThreadId);

    ParallelMethod();
    NonParallelMethod();
    
    Console.WriteLine("\nFinished...");
    Console.ReadKey(true);
}

static void NonParallelMethod()
{
    Stopwatch sw = Stopwatch.StartNew();

    for (int i = 0; i < 50; i++)
    {
        Console.WriteLine("ThreadID={0}, i={1}", Thread.CurrentThread.ManagedThreadId, i);
        SimulateProcessing();
    }

    sw.Stop();

    Console.WriteLine("It Took {0} ms with simple for", sw.ElapsedMilliseconds);
}

static void ParallelMethod()
{
    Stopwatch sw = Stopwatch.StartNew();

    Parallel.For(0, 50, i =>
    {
        Console.WriteLine("ThreadID={0}, i={1}", Thread.CurrentThread.ManagedThreadId, i);

        SimulateProcessing();
    });

    sw.Stop();

    Console.WriteLine("It Took {0} ms with Parallel For", sw.ElapsedMilliseconds);
}

static void SimulateProcessing()
{
    Thread.SpinWait(80000000);
}

Dallo screenshot seguente è possibile capire come l’utilizzo del Parallel ci permette di sfruttare a meglio l’hardware a disposizione in quanto utilizza entrambi i processori, a differenza del classico ciclo for che ne sfrutta uno solo.

001r

Ovviamente la classe Parallel non offre soltanto metodi per il ciclo for ma anche per il ForEach che funziona allo stesso modo, come mostrato di seguito:

static void ParallelForEach()
{
    int[] values = Enumerable.Range(1,50).ToArray();

    Parallel.ForEach<int>(values, i =>
    {
        Console.WriteLine("ThreadID={0}, i={1}", Thread.CurrentThread.ManagedThreadId, i);

        SimulateProcessing();
    });
}

Anche questo, come il precedente, resta un test dimostrativo della semplicità con cui si può sfruttare il Parallel Programming con il .NET Framework 4.0 e del fatto che i risultati ottenibili sono influenzabili dall’hardware che si ha a disposizione, numero di processori in primis.

Parallel.Ciauz()

.net comments edit

Il mio primo test della Beta 2 di Visual Studio 2010 non riguarda ASP.NET ma il mondo del Parallel Programming, e, nello specifico, del Parallel Linq, ossia la possibilità di utilizzare il Parallel Framework tramite la sintassi Linq.

L’utilizzo è semplicissimo e le prestazioni sono da paura se viene fatto un confronto con la stessa operazione ma senza l’utilizzo del Parallel. Ovviamente il test che riporto è banalissimo, ma serve a rendere l’idea di quanto semplice sia l’implementazione di Parallel Linq con il .NET Framework 4.0 e di che tipo di vantaggio si può trarre da un approccio di questo genere.

Come potete vedere dal codice seguente, l’unica differenza nella sintassi Linq è l’utilizzo dell’apposito Extension Method AsParallel() sull’oggetto da ciclare (Items in questo caso).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Parallel;
using System.Diagnostics;
using System.Threading;
using System.Collections;

namespace Imperugo.Test.ParallelLINQ
{
    class Program
    {
        private static IList items = new List();

        static void Main(string[] args)
        {
            PrepareData();

            ParalelTest();
            ClassicTest();

            Console.WriteLine("\nFinished...");
            Console.ReadKey(true);
        }

        private static void ParalelTest()
        {
            var results = from i in items.AsParallel() where i.SubValues.Contains(new Random(1000).Next()) select i;

            Stopwatch sw = Stopwatch.StartNew();
            IList resultsList = results.ToList();
            Console.WriteLine("{0} items", resultsList.Count());
            sw.Stop();

            Console.WriteLine("It Took {0} ms with parallel Linq", sw.ElapsedMilliseconds);
        }

        private static void ClassicTest()
        {
            var results = from i in items where i.SubValues.Contains(new Random(1000).Next()) select i;

            Stopwatch sw = Stopwatch.StartNew();
            IList resultsList = results.ToList();
            Console.WriteLine("{0} items with Linq", resultsList.Count());
            sw.Stop();

            Console.WriteLine("It Took {0} ms", sw.ElapsedMilliseconds);
        }

        static bool IsDivisibleByFive(int i)
        {
            return i % 5 == 0;
        }

        private static void PrepareData()
        {
            for (int i = 0; i < 1000000; i++)
            {
                var item = new DemoEntity
                                                {
                                                    Title = "New Title " + i,
                                                    SubValues = Enumerable.Range(1, 1000)
                                                };

                items.Add(item);
            }
        }
    }
}

Nel test è stata eseguita la stessa operazione due volte, una utilizzando il Parallel Linq (quadrato blu), ed una utilizzando Linq normalmente (quadrato rosso) su di una collection con 1.000.000 di elementi. I tempi richiesti per completare l’operazione sono ovviamente a vantaggio di Parallel Linq che conclude il ciclo con 9276 millisecondi, a differenza dei 16440 richiesti da Linq.

0023

Un aspetto molto interessante può essere lo scenario di utilizzo. Di fatto, per poter trarre vantaggio dall’utilizzo di Parallel Linq lo si deve sfruttare in elementi corposi (nel test ho utilizzato una collection con 1.000.000 di elementi, ma i vantaggi si cominciano a percepire dai 50.000 elementi in poi), altrimenti si rischia di ottenere l’effetto opposto. Ovviamente incide molto anche il numero di processori che si hanno a disposizione.
I dati riportati sono relativi ad un portatile dual core in modalità balanced, ma la differenza si nota.

Ciauz.AsParallel()

asp.net comments edit

L’HealthMonitoring di ASP.NET è sicuramente uno strumento potentissimo per tenere traccia dello stato di salute della nostra applicazione web. Uno dei suoi principali vantaggi è che dalla versione 2.0 di ASP.NET è già presente con un nutrito insieme di provider che permettono di loggare informazioni in svariati repository.
Entranto più nello specifico si hanno a disposizione i seguenti provider:

  • EventLogWebEventProvider (memorizza nell’Event Log di Windows);
  • SqlWebEventProvider (Database Sql Server 2000/05/08);
  • WmiWebEventProvider (sfrutta il Windows Management Instrumentation per gestire le notifiche);
  • SimpleMailWebEventProvider (Invia una Email);
  • TemplatedMailWebEventProvider (Invia una Email in base ad un template);
  • TraceWebEventProvider (sfrutta il trace di ASP.NET);

Ovviamente, essendo basato a provider, l’healthmonitorig offre la possibilità di realizzare ed utilizzare delle implementazioni custom, nel caso quelli precedentemente elencati non soddisfini le esigenze dello sviluppatore. Per far ciò è necessario realizzare una classe che implementi una delle apposite classi astratte messe a disposizione dal .NET Framework -WebEventProvider o BufferedWebEventProvider - ed aggiungere al loro interno propria logica.

Personalmente ritengo più che sufficienti i provider messi a disposizione e non sentirei la necessità di realizzarne uno custom se quelli messi a disposizione memorizzarsero anche le informazioni presente nella collection Data della classe Exception.
In attensa del Historical Debugger, per poter capire cosa non va nella nostra applicazione e riprodurlo, è necessario riempire il codice di logging per poter catturare e riprodurre una specifica situazione che scatena un’errore.
Purtroppo alcune volte un Logger che memorizza soltanto l’eccezione può non bastare in quanto il problema può riscontrarsi solo con alcuni paramentri e, in questi casi, è necessario memorizzare anche loro insieme all’eccezzione.

Per far ciò una buona pratica è quella di inserire questi valori nell’apposito Dictionary Data presente nell’oggetto Exception in modo da avere in un’unico oggetto sia lo stack che le informazioni legate all’eccezione.
Lo snippet seguente mostra come sfruttarlo:

public static void Send(Uri sourceUrl, Uri targetUrl)
{
    try
    {
        //do something
    }
    catch (Exception ex)
    {
        ex.Data.Add("Source Url: ", sourceUrl);
        ex.Data.Add("Target Url: ", targetUrl);

        Log.Log.General.Error("Send PingBack Error", ex);
    }
}

Purtroppo i provider dell’HealthMonitoring messi a disposizione dal .NET Framework non memorizzano questo tipo di informazioni, il che ci obbliga (se siamo interessati a tener traccia di queste informazioni) a scriverci un provider custom che dovrebbe essere più o meno così:

public class HealthMonitorDataBaseProvider : BufferedWebEventProvider
{
    public override void ProcessEvent(WebBaseEvent eventRaised)
    {
        if (UseBuffering)
            base.ProcessEvent(eventRaised);
        else
            Save(new[] { eventRaised });
    }

    public override void ProcessEventFlush(WebEventBufferFlushInfo flushInfo)
    {
        Save(flushInfo.Events);
    }

    private static void Save(ICollection eventCollection)
    {
        WebRequestInformation requestInformation = null;
        Exception errorException = null;
        MyLog item = new MyLog();

        foreach (WebBaseEvent eventRaised in eventCollection)
        {
            //popolo myLog 
            
            if (eventRaised is WebBaseErrorEvent)
                errorException = ((WebBaseErrorEvent)eventRaised).ErrorException;

            if (errorException != null)
            {
                StringBuilder sb = new StringBuilder(errorException.ToString());

                if (errorException.Data != null && errorException.Data.Count > 0)
                {
                    sb.Append(Environment.NewLine);

                    foreach (DictionaryEntry de in errorException.Data)
                    {
                        sb.Append(de.Key.ToString());
                        sb.Append(": ");
                        sb.Append(de.Value.ToString());
                        sb.Append(Environment.NewLine);
                    }
                }

                logInstance.Details = sb.ToString();
            }

            new LogService().Save(item);
        }
    }
}

stay connected!

.net comments edit

Non è passata neanche una settimana dall’uscita della Beta 2 di Visual Studio 2010 e sul sito Microsoft è già disponibile il Training Kit che include parecchio materiale, presentazioni, hands-in labs e demo.

Il materiale è bello corposo, sono 95 Mb che includono i seguenti argomenti:

  • C# 4.0
  • Visual Basic 10
  • F#
  • Parallel Extensions
  • Windows Communication Foundation
  • Windows Workflow
  • Windows Presentation Foundation
  • ASP.NET 4
  • Windows 7
  • Entity Framework
  • ADO.NET Data Services
  • Managed Extensibility Framework
  • Visual Studio Team System

Il download è disponibile qui ed è basato sulla Beta 2 e, come potete vedere dall’elenco, non è presente del materiale su ASP.NET MVC 2, motivo per cui non potete mancare qui.

more to come...stay connected!

asp.net comments edit

Ieri sera stavo valutando l’idea di convertire Dexter dalla versione 1.0 di ASP.NET MVC alla versione 2.0, per poter sfruttare tutte le nuove catatteristiche offerte da Visual Studio 2010 Beta 2 che, come comunicato dal PM Phil Haack qui, non supporterà la versione 1 di ASP.NET MVC.

Il passaggio non è particolarmente complesso, basta cambiare i riferimenti nei vari web.config (web application, test, ecc.) delle librerie routing e di mvc, i puntamenti nei vari progetti e l’applicazione è pronta per girare con la 2.0. 
Già dalla Beta 1 Scott Hanselman aveva mostrato, tramite il suo blog (qui), come realizzare una console application che convertisse il progetto in automatico; proprio da questo post Eilon Lipton ha realizzato una piccola windows form che, data una solution, converte in automatico tutti i progetti presenti al suo interno ed i vari files di configurazione.

L’applicazione sembra girare bene, senza particolari controindicazioni, ma, nel caso in cui abbiate effettuato dei forti cambiamenti alla struttura delle folders, potreste intercorrere in qualche errore :) : proprio per questo motivo non mi è stato possibile convertire dexter con questo tool.
Purtroppo, non avendo più la cartella Scripts, il tool è andato in errore cercando di caricare le librerie aggiornate di jQuery ed Ajax. Ovviamente ho inviato una segnalazione all’autore spiegando la situazione e non ci resta che sperare in un aggiornamento.

Sotto uno screenshot dell’applicazione:

mvc1

Maggiori informazioni ed il download sono disponibili al blog dell’autore (qui).

eventi comments edit

n156793021630_4016[1]_thumb Lo UserGroup siciliano OrangeDotNet fa la sua prima uscita ufficiale con un evento che prende spunto dal Party per Windows 7, per diventare un vero e proprio meeting live serale nel puro stile di community tecnologica.

Lunedì prossimo è di scena il Windows 7, party with OrangeDotNet in cui ci saranno una serie di mini-sessioni e, da quello che ho capito, anche dei PC su cui fare delle prove di persona.

Se volete incontrare janky e soci... presentatevi il 26 novembre alle 18 a Paternò (CT)...questo è l'evento su Facebook che riassume tutti i dati.
Maggiori info le trovate qui.

In bocca al lupo ragazzi!

PS: tenete d'occhio orange...perchè magari tra un po’ potrei essere in quel di Sicilia a parlare di MVC/ASPNET.....more to come...stay connected!

eventi comments edit

Se volete approfondire ASP.NET MVC 2, che è presente in questa densissima release di Microsoft, possiamo incontrarci lunedì 16 novembre a Bologna, dove avrò l’opportunità di parlare appunto di questa nuovissima release insieme a Salvo.
La giornata sarà interamente orientata al web, infatti prima di me e Salvo, ci sarà Pietro a parlarci di Silverlight e .NET Ria Services in applicazioni Business.

Il taglio della sessione sarà parecchio pragmatico, ricco di codice e di esempi pratici riutilizzabili in applicazioni reali, e non mancheranno le sorprese, quindi non avete scuse per mancare :).

Un ringraziamento speciale va ad Alessandro e a tutti i ragazzi di DotDotNet per avermi offerto la possibilità di condividere la mia passione.

L’evento, organizzato da Microsoft Italia e DotDotNet, sarà totalmente gratuito e gentilmente ospitato dal
Consorzio Almacube, presso la Facoltà di Agraria dell'Università di Bologna in Via Fanin, 48 – Bologna.

Per registrarsi basta andare qui, mentre per abstract ed ulteriori info qui.

Non mancate!