<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>ASP.NET MVC</title>
        <link>http://blogs.ugidotnet.org/dsantarelli/category/ASP.NET MVC.aspx</link>
        <description>ASP.NET MVC</description>
        <language>it-IT</language>
        <copyright>Dario Santarelli</copyright>
        <generator>Subtext Version 2.6.0.0</generator>
        <item>
            <title>Migliorare le performance di un’applicazione ASP.NET MVC</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2011/01/11/migliorare-le-performance-di-unapplicazione-asp.net-mvc-again.aspx</link>
            <description>&lt;p&gt;Esistono molti aspetti da tenere in considerazione quando si parla di performance di applicazioni Web. Infatti, le problematiche legate al protocollo HTTP spesso scavalcano il prode tentativo di scrivere codice server-side e client-side ottimizzato, poiché migliorare le performance di un’ applicazione Web significa anche minimizzare il traffico dati tra client e server. Le best practices per velocizzare il caricamento delle pagine web non sono poche, come si può appurare semplicemente consultando l’utilissimo documento di &lt;a href="http://developer.yahoo.com/"&gt;Yahoo Developer Network&lt;/a&gt; dal titolo “&lt;a href="http://developer.yahoo.com/performance/rules.html"&gt;Best Practices for Speeding Up Your Web Site&lt;/a&gt;”  (parliamo di 35 best practices divise in 7 categorie!)     &lt;br /&gt;
In questo post ho cercato di aggregare una serie di appunti/approfondimenti relativi a tecniche comuni di miglioramento delle performance di un’applicazione ASP.NET MVC (e non solo) in base alla mia esperienza. I punti su cui cercherò di soffermarmi in particolare sono:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Output Cache &lt;/li&gt;
    &lt;li&gt;Compressione HTTP  &lt;/li&gt;
    &lt;li&gt;Minimizzazione e combinazione di risorse esterne (JavaScript e Css)  &lt;/li&gt;
    &lt;li&gt;Minimizzazione del markup HTML  &lt;/li&gt;
    &lt;li&gt;Ottimizzazione della generazione degli URL &lt;/li&gt;
    &lt;li&gt;Note di configurazione &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://blogs.ugidotnet.org/dsantarelli/archive/2011/01/11/migliorare-le-performance-di-unapplicazione-asp.net-mvc.aspx"&gt;&lt;strong&gt;Leggi il post &amp;gt;&amp;gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/99617.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2011/01/11/migliorare-le-performance-di-unapplicazione-asp.net-mvc-again.aspx</guid>
            <pubDate>Tue, 11 Jan 2011 21:42:43 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2011/01/11/migliorare-le-performance-di-unapplicazione-asp.net-mvc-again.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/99617.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/99617.aspx</trackback:ping>
        </item>
        <item>
            <title>Migliorare le performance di un’applicazione ASP.NET MVC</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2011/01/11/migliorare-le-performance-di-unapplicazione-asp.net-mvc.aspx</link>
            <description>&lt;p&gt;Esistono molti aspetti da tenere in considerazione quando si parla di performance di applicazioni Web. Infatti, le problematiche legate al protocollo HTTP spesso scavalcano il prode tentativo di scrivere codice server-side e client-side ottimizzato, poiché migliorare le performance di un’ applicazione Web significa anche minimizzare il traffico dati tra client e server. Le best practices per velocizzare il caricamento delle pagine web non sono poche, come si può appurare semplicemente consultando l’utilissimo documento di &lt;a href="http://developer.yahoo.com/"&gt;Yahoo Developer Network&lt;/a&gt; dal titolo “&lt;a href="http://developer.yahoo.com/performance/rules.html"&gt;Best Practices for Speeding Up Your Web Site&lt;/a&gt;”  (parliamo di 35 best practices divise in 7 categorie!)     &lt;br /&gt;
In questo post ho cercato di aggregare una serie di appunti/approfondimenti relativi a tecniche comuni di miglioramento delle performance di un’applicazione ASP.NET MVC (e non solo) in base alla mia esperienza. I punti su cui cercherò di soffermarmi in particolare sono:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Output Cache &lt;/li&gt;
    &lt;li&gt;Compressione HTTP  &lt;/li&gt;
    &lt;li&gt;Minimizzazione e combinazione di risorse esterne (JavaScript e Css)  &lt;/li&gt;
    &lt;li&gt;Minimizzazione del markup HTML  &lt;/li&gt;
    &lt;li&gt;Ottimizzazione della generazione degli URL &lt;/li&gt;
    &lt;li&gt;Note di configurazione &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;       &lt;br /&gt;
Output cache         &lt;br /&gt;
&lt;br /&gt;
&lt;/font&gt;&lt;/strong&gt;Un’ applicazione Web dovrebbe sempre prevedere una politica di &lt;a href="http://en.wikipedia.org/wiki/HTTP_cache"&gt;caching&lt;/a&gt; delle risposte HTTP sia client-side (browser + proxy) che server-side, in modo tale che il contenuto di una risposta HTTP non venga rigenerato inutilmente ogni volta che il client ne effettua la richiesta. Il modo più semplice ed immediato per abilitare il caching in un’applicazione MVC è aggiungere l’attributo [&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.outputcacheattribute.aspx"&gt;OutputCache&lt;/a&gt;] a livello di action. Questa funzionalità è praticamente identica a quella che incontriamo nelle Web Forms, ma cambia nel fatto che non deve essere applicata a livello di View (quindi non dovremmo usare la direttiva &lt;em&gt;&amp;lt;%@ OutputCache %&amp;gt;&lt;/em&gt;), anche perché non avrebbe molto senso nel pattern MVC, in cui la View dovrebbe essere agnostica rispetto alle politiche di caching. L’unica proprietà che non è supportata nella versione MVC è &lt;em&gt;VaryByControl&lt;/em&gt;.     &lt;br /&gt;
In genere è sempre consigliabile cercare di estrarre le impostazioni di caching nel web.config definendo dei profili, in modo da non dover ricompilare il sorgente ogni volta che cambiamo le nostre strategie di caching. Quindi, nel controller dovremmo scrivere qualcosa del genere:&lt;/p&gt;
&lt;pre style="margin: 0cm 0cm 0pt;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;class&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;HomeController&lt;/font&gt;&lt;/span&gt; : &lt;span&gt;&lt;font color="#2b91af"&gt;Controller&lt;br /&gt;&lt;/font&gt;&lt;/span&gt;{&lt;br /&gt;  [&lt;span&gt;&lt;font color="#2b91af"&gt;OutputCache&lt;/font&gt;&lt;/span&gt;(CacheProfile=&lt;span&gt;&lt;font color="#a31515"&gt;"MyCacheProfile"&lt;/font&gt;&lt;/span&gt;)]&lt;br /&gt;  &lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;ActionResult&lt;/font&gt;&lt;/span&gt; Index()&lt;br /&gt;  {                             &lt;br /&gt;    &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; View();&lt;br /&gt;  }&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US"&gt;&lt;font face="Consolas"&gt;&lt;font style="font-size: 11pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" /&gt;&lt;/p&gt;
&lt;span lang="EN-US"&gt; &lt;span lang="EN-US"&gt; &lt;span lang="EN-US"&gt; &lt;span lang="EN-US"&gt;
&lt;p&gt;     &lt;br /&gt;
e nel web.config&lt;/p&gt;
&lt;pre style="margin: 0cm 0cm 0pt;"&gt;&lt;font face="Consolas"&gt;&lt;span lang="EN-US"&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;font color="#a31515"&gt;configuration&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span lang="EN-US"&gt;&lt;font color="#0000ff"&gt;&amp;gt; &lt;br /&gt; &amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;font color="#a31515"&gt;system.web&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span lang="EN-US" /&gt;&lt;/pre&gt;
&lt;span lang="EN-US"&gt; &lt;span lang="EN-US"&gt; &lt;span lang="EN-US"&gt; &lt;span lang="EN-US"&gt;
&lt;pre style="margin: 0cm 0cm 0pt;"&gt;&lt;font face="Consolas"&gt;&lt;span lang="EN-US"&gt;&lt;font color="#0000ff"&gt;&lt;span&gt;   &lt;/span&gt;&amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;font color="#a31515"&gt;caching&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US"&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span lang="EN-US"&gt;&lt;br /&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;     &amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;outputCacheSettings&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;       &amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;outputCacheProfiles&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;         &amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;add&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#ff0000"&gt;name&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt;MyCacheProfile&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#ff0000"&gt;enabled&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#ff0000"&gt;duration&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt;600&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#ff0000"&gt;varyByParam&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt;None&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#ff0000"&gt;location&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt;Any&lt;/font&gt;&lt;/span&gt;"&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt; /&amp;gt;&lt;br /&gt; &lt;span&gt;          &lt;/span&gt;...&lt;/font&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;       &amp;lt;/&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;outputCacheProfiles&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;     &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;outputCacheSettings&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;    &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;caching&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;br /&gt;  &lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;font face="Consolas"&gt;&lt;font color="#0000ff"&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font color="#a31515"&gt;system.web&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span /&gt;&lt;/pre&gt;
&lt;span&gt; &lt;span&gt; &lt;span&gt; &lt;span&gt;
&lt;pre style="margin: 0cm 0cm 0pt;"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;lt;/&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;configuration&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span /&gt;&lt;/pre&gt;
&lt;span&gt; &lt;span&gt; &lt;span&gt; &lt;span&gt;
&lt;p&gt;           &lt;br /&gt;
Ovviamente il controllo programmatico della cache di ASP.NET è sempre a disposizione tramite la solita classe &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx"&gt;System.Web.Caching.Cache&lt;/a&gt;. L’unica e non indifferente limitazione di questo approccio risiede nel fatto che la cache è in-process rispetto all’applicazione web e dunque non è distribuita. In applicazioni che richiedono un alto grado di scalabilità, invece, sarebbe preferibile prendere in considerazione architetture di caching distribuito (es. Velocity). A riguardo, consiglio la lettura di questo articolo di Stephen Walther: &lt;a href="http://stephenwalther.com/blog/archive/2008/08/28/asp-net-mvc-tip-39-use-the-velocity-distributed-cache.aspx"&gt;ASP.NET MVC Tip #39 – Use the Velocity Distributed Cache&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;           &lt;br /&gt;
&lt;strong&gt;&lt;font size="3"&gt;Compressione HTTP                &lt;br /&gt;
&lt;/font&gt;&lt;/strong&gt;            &lt;br /&gt;
In conformità alla &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html"&gt;specifica HTTP/1.1&lt;/a&gt;, i web server ed i browser moderni supportano l’elaborazione di &lt;a href="http://en.wikipedia.org/wiki/HTTP_compression"&gt;contenuti compressi&lt;/a&gt; secondo standard di compressione come il &lt;a href="http://www.ietf.org/rfc/rfc1952.txt"&gt;GZIP&lt;/a&gt; ed il (migliore) &lt;a href="http://www.ietf.org/rfc/rfc1951.txt"&gt;DEFLATE&lt;/a&gt; al fine di ridurre sensibilmente la banda occupata dal traffico HTTP. Lato server, la soluzione più scalabile per comprimere contenuti statici e dinamici prevede lo sfruttamento delle feature del Web Server piuttosto che della web application, ovviamente a fronte di ragionevoli &lt;a href="http://weblogs.asp.net/owscott/archive/2009/02/22/iis-7-compression-good-bad-how-much.aspx"&gt;valutazioni sul carico computazionale&lt;/a&gt; che il server deve sostenere soprattutto per gestire la compressione di contenuti dinamici. Nelle versioni di IIS precedenti alla 6.0, la funzionalità di compressione HTTP non è built-in e richiede comunque l’utilizzo di strumenti di terze parti (come &lt;a href="https://secure.xcache.com/"&gt;XCompress&lt;/a&gt;). &lt;/p&gt;
&lt;p&gt;In IIS6.0, invece, abbiamo l’introduzione di features di compressione statica (con cache su disco) e dinamica (senza cache su disco) che richiedono una modifica al metabase (%WINDIR%\system32\inetsrv\metabase.xml), al fine di abilitare gli schemi di compressione gzip e deflate su contenuti identificabili solamente &lt;strong&gt;in base al tipo di estensione&lt;/strong&gt; (es. .aspx, .html etc). Per questo motivo, le applicazioni ASP.NET MVC deployate su IIS6 vanno incontro ad una serie di problematiche legate al fatto che le URL senza estensione forniscono un bel 404, ed anche se si implementa un URL rewrite o un “wildcard” mapping la compressione built-in di contenuti dinamici di IIS6.0 non ha più effetto poiché non sussiste alcun match con le estensioni specificate nel metabase. Quindi, se vogliamo avere la compressione sotto controllo, dobbiamo ricorrere ad un HttpModule, come viene spiegato molto bene in &lt;a href="http://omaralzabir.com/deploy_asp_net_mvc_on_iis_6__solve_404__compression_and_performance_problems/"&gt;questo post&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Il problema viene risolto alla radice a partire da IIS7.0 grazie alla nuova sezione di configurazione &lt;a href="http://www.iis.net/ConfigReference/system.webServer/httpCompression"&gt;&amp;lt;httpCompression&amp;gt;&lt;/a&gt;, che va a sostituire le precedenti configurazioni del metabase di IIS6.0 e ci permette di abilitare la compressione &lt;strong&gt;in base ai tipi MIME&lt;/strong&gt; a livello di server, web site o web application attraverso diverse strade: IIS Manager, la command line di Appcmd.exe, il web.config e le API managed. Un grande vantaggio di IIS7+ inoltre è la capacità automatica di interrompere/riprendere la compressione a seconda che il carico di CPU superi/scenda sotto una soglia configurabile (vedi attributi &lt;em&gt;dynamicCompressionDisableCpuUsage&lt;/em&gt; e &lt;em&gt;dynamicCompressionEnableCpuUsage&lt;/em&gt;&lt;font face="Verdana"&gt;). &lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Nel caso in cui non fosse disponibile la possibilità di accedere alla configurazione del web server, siamo costretti a prendere la strada applicativa. Analogamente al classico mondo ASP.NET, anche in ASP.NET MVC la gestione della compressione dei contenuti può essere ottenuta tramite un HttpModule (ad esempio &lt;a href="http://blowery.org/httpcompress/"&gt;HttpCompress&lt;/a&gt;) in grado di applicare la compressione all’output stream della risposta HTTP. In genere, questa è una soluzione semplice e riusabile (forse meno performante) che permette di non intaccare almeno nella teoria una web application preesitente. &lt;/p&gt;
&lt;p&gt;Un’ulteriore possibilità totalmente programmatica per ASP.NET MVC è la realizzazione di un filtro custom che a livello di controller o di singola action vada ad intercettare la risposta HTTP ed applicare al volo la compressione (come farebbe un HttpModule) sfruttando le classi del framework &lt;a href="http://msdn.microsoft.com/it-it/library/system.io.compression.gzipstream.aspx"&gt;GZipStream&lt;/a&gt; e &lt;a href="http://msdn.microsoft.com/it-it/library/system.io.compression.deflatestream.aspx"&gt;DeflateStream&lt;/a&gt;. Ecco un esempio di action filter:&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font color="#0000ff" face="Consolas"&gt;public&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Consolas"&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;class&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;CompressFilterAttribute&lt;/font&gt;&lt;/span&gt; : &lt;span&gt;&lt;font color="#2b91af"&gt;ActionFilterAttribute&lt;/font&gt;&lt;/span&gt;                 &lt;br /&gt;
{                 &lt;br /&gt;
    &lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt;&lt;/span&gt; OnResultExecuted(&lt;span&gt;&lt;font color="#2b91af"&gt;ResultExecutedContext&lt;/font&gt;&lt;/span&gt; filterContext)                 &lt;br /&gt;
    {                 &lt;br /&gt;
       &lt;span&gt;&lt;font color="#2b91af"&gt;HttpRequestBase&lt;/font&gt;&lt;/span&gt; request = filterContext.HttpContext.Request;                 &lt;br /&gt;
       &lt;span&gt;&lt;font color="#0000ff"&gt;string&lt;/font&gt;&lt;/span&gt; acceptEncoding = request.Headers[&lt;span&gt;&lt;font color="#a31515"&gt;"Accept-Encoding"&lt;/font&gt;&lt;/span&gt;];                 &lt;br /&gt;
             &lt;br /&gt;
       &lt;span&gt;&lt;font color="#0000ff"&gt;if&lt;/font&gt;&lt;/span&gt; (&lt;span&gt;&lt;font color="#0000ff"&gt;string&lt;/font&gt;&lt;/span&gt;.IsNullOrEmpty(acceptEncoding)) &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt;;                 &lt;br /&gt;
&lt;span&gt; &lt;/span&gt;                 &lt;br /&gt;
       acceptEncoding = acceptEncoding.ToLowerInvariant();                 &lt;br /&gt;
&lt;br /&gt;
       &lt;span&gt;&lt;font color="#2b91af"&gt;HttpResponseBase&lt;/font&gt;&lt;/span&gt; response = filterContext.HttpContext.Response;                 &lt;br /&gt;
&lt;span&gt; &lt;/span&gt;                 &lt;br /&gt;
       &lt;span&gt;&lt;font color="#0000ff"&gt;if&lt;/font&gt;&lt;/span&gt; (acceptEncoding.Contains(&lt;span&gt;&lt;font color="#a31515"&gt;"deflate"&lt;/font&gt;&lt;/span&gt;)) &lt;span&gt;&lt;font color="#008000"&gt;// Priority to DEFLATE compression schema&lt;/font&gt;&lt;/span&gt;                 &lt;br /&gt;
       {                 &lt;br /&gt;
         response.AppendHeader(&lt;span&gt;&lt;font color="#a31515"&gt;"Content-Encoding"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"deflate"&lt;/font&gt;&lt;/span&gt;);                 &lt;br /&gt;
         response.Filter = &lt;span&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;DeflateStream&lt;/font&gt;&lt;/span&gt;(response.Filter, &lt;span&gt;&lt;font color="#2b91af"&gt;CompressionMode&lt;/font&gt;&lt;/span&gt;.Compress);                 &lt;br /&gt;
       }                 &lt;br /&gt;
       &lt;span&gt;&lt;font color="#0000ff"&gt;else&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;if&lt;/font&gt;&lt;/span&gt; (acceptEncoding.Contains(&lt;span&gt;&lt;font color="#a31515"&gt;"gzip"&lt;/font&gt;&lt;/span&gt;))                 &lt;br /&gt;
       {                 &lt;br /&gt;
          response.AppendHeader(&lt;span&gt;&lt;font color="#a31515"&gt;"Content-Encoding"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"gzip"&lt;/font&gt;&lt;/span&gt;);                 &lt;br /&gt;
          response.Filter = &lt;span&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;GZipStream&lt;/font&gt;&lt;/span&gt;(response.Filter, &lt;span&gt;&lt;font color="#2b91af"&gt;CompressionMode&lt;/font&gt;&lt;/span&gt;.Compress);                 &lt;br /&gt;
       }                 &lt;br /&gt;
    }                 &lt;br /&gt;
}&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;Minimizzazione e combinazione di risorse JavaScript e CSS                &lt;br /&gt;
&lt;/font&gt;&lt;/strong&gt;            &lt;br /&gt;
Un’altra importante tip per ottimizzare il traffico HTTP tra client e server è data dalla minimizzazione e la combinazione delle risorse esterne ad una pagina Web, in modo da ridurre massicciamente il numero complessivo di richieste HTTP generate dal browser. Esiste un progetto molto interessante su CodePlex che affronta questa problematica sia per applicazioni ASP.NET Web Forms che per applicazioni ASP.NET MVC. Si tratta di &lt;a href="http://combres.codeplex.com/"&gt;&lt;strong&gt;Combres&lt;/strong&gt;&lt;/a&gt;, una libreria .NET che permette di organizzare JavaScript e CSS in diversi insiemi, ad ognuno dei quali viene associata una sezione di configurazione nel web.config. Le risorse specificate in ciascun insieme vengono minimizzate, combinate, compresse e messe in cache in modo da poter essere trasmesse in un singolo round-trip HTTP. Per informazioni dettagliate sull’utilizzo di questa libreria rimando al completo &lt;a href="http://www.codeproject.com/KB/aspnet/combres2.aspx"&gt;articolo su CodeProject&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;           &lt;br /&gt;
&lt;strong&gt;&lt;font size="3"&gt;Minimizzazione del markup HTML                &lt;br /&gt;
&lt;/font&gt;&lt;/strong&gt;            &lt;br /&gt;
Anche la rimozione degli spazi bianchi che si frappongono tra i tag all’interno di un documento HTML può ridurre il tempo di caricamento di una pagina Web, poiché ne riduce le dimensioni nonché ne favorisce il parsing da parte del browser. Anche questa funzionalità può essere ottenuta tramite un modulo HTTP, come &lt;a href="http://madskristensen.net/post/A-whitespace-removal-HTTP-module-for-ASPNET-20.aspx"&gt;questo&lt;/a&gt; di Mads Kristensen. In ASP.NET MVC inoltre si può pensare di realizzare un action filter. Molto semplicemente:&lt;/p&gt;
&lt;pre style="margin: 0cm 0cm 0pt;"&gt;&lt;span style="font-family: ;"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;class&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;HtmlWhitespaceFilter&lt;/font&gt;&lt;/span&gt; : &lt;span&gt;&lt;font color="#2b91af"&gt;ActionFilterAttribute&lt;br /&gt;&lt;/font&gt;&lt;/span&gt;{&lt;br /&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;  public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt;&lt;/span&gt; OnResultExecuted(&lt;span&gt;&lt;font color="#2b91af"&gt;ResultExecutedContext&lt;/font&gt;&lt;/span&gt; filterContext)&lt;br /&gt;  {&lt;br /&gt;&lt;span&gt;&lt;font color="#2b91af"&gt;    HttpResponseBase&lt;/font&gt;&lt;/span&gt; response = filterContext.HttpContext.Response;            &lt;span&gt;&lt;font color="#0000ff"&gt;    &lt;/font&gt;&lt;/span&gt;     &lt;br /&gt;    &lt;span&gt;&lt;font color="#0000ff"&gt;string&lt;/font&gt;&lt;/span&gt; contentType = response.ContentType.Trim().ToLowerInvariant();                 &lt;br /&gt;    &lt;span&gt;&lt;font color="#0000ff"&gt;if&lt;/font&gt;&lt;/span&gt; (contentType == &lt;span&gt;&lt;font color="#a31515"&gt;"text/html"&lt;/font&gt;&lt;/span&gt; || contentType == &lt;span&gt;&lt;font color="#a31515"&gt;"application/xhtml+xml"&lt;/font&gt;&lt;/span&gt; ||&lt;br /&gt;        contentType == &lt;span&gt;&lt;font color="#a31515"&gt;"text/xml"&lt;/font&gt;&lt;/span&gt; || contentType == &lt;span&gt;&lt;font color="#a31515"&gt;"application/xml"&lt;/font&gt;&lt;/span&gt;)&lt;br /&gt;      {                &lt;br /&gt;        response.Filter = &lt;span&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;HtmlWhitespaceFilterStream&lt;/font&gt;&lt;/span&gt;(response.Filter);&lt;br /&gt;      }           &lt;br /&gt;  }&lt;br /&gt;}&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Riporto per completezza l’implementazione della classe &lt;em&gt;HtmlWhitespaceFilterStream&lt;/em&gt;, che internamente utilizza delle banali regular expression per eliminare gli spazi vuoti tra i vari tag del documento (X)HTML.&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font color="#0000ff" face="Consolas"&gt;public&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Consolas"&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;class&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;HtmlWhitespaceFilterStream&lt;/font&gt;&lt;/span&gt; : &lt;span&gt;&lt;font color="#2b91af"&gt;Stream&lt;/font&gt;&lt;/span&gt;                 &lt;br /&gt;
{                 &lt;br /&gt;
&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font color="#000000"&gt;  &lt;/font&gt;private&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;Stream&lt;/font&gt;&lt;/span&gt; _stream;                 &lt;br /&gt;
                       &lt;span&gt;&lt;font color="#0000ff"&gt;        &lt;/font&gt;&lt;/span&gt;                &lt;br /&gt;
  &lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;bool&lt;/font&gt;&lt;/span&gt; CanRead { &lt;span&gt;&lt;font color="#0000ff"&gt;get&lt;/font&gt;&lt;/span&gt; { &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;; } }                 &lt;br /&gt;
  &lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;bool&lt;/font&gt;&lt;/span&gt; CanSeek { &lt;span&gt;&lt;font color="#0000ff"&gt;get&lt;/font&gt;&lt;/span&gt; { &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;; } }                 &lt;br /&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;bool&lt;/font&gt;&lt;/span&gt; CanWrite { &lt;span&gt;&lt;font color="#0000ff"&gt;get&lt;/font&gt;&lt;/span&gt; { &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;; } }                 &lt;br /&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt;&lt;/span&gt; Flush() { _stream.Flush(); }                 &lt;br /&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;long&lt;/font&gt;&lt;/span&gt; Length { &lt;span&gt;&lt;font color="#0000ff"&gt;get&lt;/font&gt;&lt;/span&gt; { &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; _stream.Length; } }&lt;span&gt; &lt;/span&gt;                 &lt;br /&gt;
&lt;span&gt;&lt;font color="#0000ff"&gt;  public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;long&lt;/font&gt;&lt;/span&gt; Position                 &lt;br /&gt;
  {                 &lt;br /&gt;
    &lt;span&gt;&lt;font color="#0000ff"&gt;get&lt;/font&gt;&lt;/span&gt; { &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; _stream.Position; }                 &lt;br /&gt;
    &lt;span&gt;&lt;font color="#0000ff"&gt;set&lt;/font&gt;&lt;/span&gt; { _stream.Position = &lt;span&gt;&lt;font color="#0000ff"&gt;value&lt;/font&gt;&lt;/span&gt;; }                 &lt;br /&gt;
  }                 &lt;br /&gt;
&lt;span&gt; &lt;/span&gt;                 &lt;br /&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; HtmlWhitespaceFilterStream(&lt;span&gt;&lt;font color="#2b91af"&gt;Stream&lt;/font&gt;&lt;/span&gt; stream) { _stream = stream; }                 &lt;br /&gt;
&lt;span&gt; &lt;/span&gt;                 &lt;br /&gt;
&lt;span&gt;&lt;font color="#0000ff"&gt;&lt;font color="#000000"&gt;  &lt;/font&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; Read(&lt;span&gt;&lt;font color="#0000ff"&gt;byte&lt;/font&gt;&lt;/span&gt;[] buffer, &lt;span&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; offset, &lt;span&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; count) &lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Consolas"&gt;{ &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; _stream.Read(buffer, offset, count); }                 &lt;br /&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;long&lt;/font&gt;&lt;/span&gt; Seek(&lt;span&gt;&lt;font color="#0000ff"&gt;long&lt;/font&gt;&lt;/span&gt; offset, &lt;span&gt;&lt;font color="#2b91af"&gt;SeekOrigin&lt;/font&gt;&lt;/span&gt; origin) { &lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; _stream.Seek(offset, origin); }                 &lt;br /&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt;&lt;/span&gt; SetLength(&lt;span&gt;&lt;font color="#0000ff"&gt;long&lt;/font&gt;&lt;/span&gt; value) { _stream.SetLength(value); }                 &lt;br /&gt;
&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt;&lt;/span&gt; Close() { _stream.Close(); }                 &lt;br /&gt;
&lt;span&gt;  &lt;br /&gt;
  &lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt;&lt;/span&gt; Write(&lt;span&gt;&lt;font color="#0000ff"&gt;byte&lt;/font&gt;&lt;/span&gt;[] buffer, &lt;span&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; offset, &lt;span&gt;&lt;font color="#0000ff"&gt;int&lt;/font&gt;&lt;/span&gt; count)                 &lt;br /&gt;
  {            &lt;br /&gt;
    &lt;span&gt;&lt;font color="#0000ff"&gt;string&lt;/font&gt;&lt;/span&gt; html = System.Text.&lt;span&gt;&lt;font color="#2b91af"&gt;Encoding&lt;/font&gt;&lt;/span&gt;.UTF8.GetString(buffer);                 &lt;br /&gt;
&lt;strong&gt;    &lt;/strong&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="font-family: ;"&gt;&lt;font face="Consolas"&gt;&lt;strong&gt;html = &lt;span&gt;&lt;font color="#2b91af"&gt;Regex&lt;/font&gt;&lt;/span&gt;.Replace(html, &lt;span&gt;&lt;font color="#a31515"&gt;@"\s+&amp;lt;"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"&amp;lt;"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#2b91af"&gt;RegexOptions&lt;/font&gt;&lt;/span&gt;.Singleline);                   &lt;br /&gt;
    html = &lt;span&gt;&lt;font color="#2b91af"&gt;Regex&lt;/font&gt;&lt;/span&gt;.Replace(html, &lt;span&gt;&lt;font color="#a31515"&gt;@"&amp;gt;\s+"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"&amp;gt;"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#2b91af"&gt;RegexOptions&lt;/font&gt;&lt;/span&gt;.Singleline);&lt;/strong&gt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Consolas"&gt;                &lt;br /&gt;
    &lt;span&gt;&lt;font color="#0000ff"&gt;byte&lt;/font&gt;&lt;/span&gt;[] outdata = System.Text.&lt;span&gt;&lt;font color="#2b91af"&gt;Encoding&lt;/font&gt;&lt;/span&gt;.UTF8.GetBytes(html);                 &lt;br /&gt;
    _stream.Write(outdata, 0, outdata.Length);                 &lt;br /&gt;
  }                 &lt;br /&gt;
} &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Consolas"&gt;            &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="3"&gt;&lt;strong&gt;Ottimizzazione della generazione degli URL&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Un aspetto che può intaccare le performance di applicazioni ASP.NET MVC stressate da migliaia richieste al minuto è il modo in cui vengono generati gli URL virtuali nelle View tramite gli helper &lt;em&gt;Html.ActionLink()&lt;/em&gt;, &lt;em&gt;Html.RouteLink()&lt;/em&gt;, &lt;em&gt;Url.Action()&lt;/em&gt; e &lt;em&gt;Url.RouteUrl()&lt;/em&gt;. In &lt;a href="http://www.chadmoran.com/blog/2009/4/21/optimizing-url-generation-in-aspnet-mvc-part-1.html"&gt;questo post&lt;/a&gt; di Chad Moran viene mostrato in dettaglio come un performance test sulla generazione massiva di URL ci dovrebbe spingere verso la rinuncia delle comodità che ci vengono offerte dalle lambda expression e dagli anonymous object.             &lt;br /&gt;
Sostanzialmente, per beneficiare di performance migliori, dovremmo preferire una sintassi di questo tipo…&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Consolas"&gt;Html.ActionLink(&lt;span&gt;&lt;font color="#a31515"&gt;"Link"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"Index"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"Home"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;RouteValueDictionary&lt;/font&gt;&lt;/span&gt; { { &lt;span&gt;&lt;font color="#a31515"&gt;"name"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"Mario"&lt;/font&gt;&lt;/span&gt; }, { &lt;span&gt;&lt;font color="#a31515"&gt;"age"&lt;/font&gt;&lt;/span&gt;, 56 } })&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;           &lt;br /&gt;
…ad una di questo tipo…&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Consolas"&gt;Html.ActionLink(&lt;span&gt;&lt;font color="#a31515"&gt;"Link"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"Index"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#a31515"&gt;"Home"&lt;/font&gt;&lt;/span&gt;, &lt;span&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; { name = &lt;span&gt;&lt;font color="#a31515"&gt;"Mario"&lt;/font&gt;&lt;/span&gt;, age = 56 })&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;           &lt;br /&gt;
…o ancora peggio (per le performance) di questo tipo …             &lt;br /&gt;
&lt;br /&gt;
&lt;span lang="EN-US" style="line-height: 12pt; font-family: ;"&gt;&lt;font face="Consolas"&gt;Html.ActionLink&amp;lt;HomeController&amp;gt;(c =&amp;gt; c.Index(&lt;span&gt;&lt;font color="#a31515"&gt;"Mario"&lt;/font&gt;&lt;/span&gt;,56), &lt;span&gt;&lt;font color="#a31515"&gt;"Link"&lt;/font&gt;&lt;/span&gt;)&lt;/font&gt;&lt;/span&gt;             &lt;br /&gt;
&lt;br /&gt;
Come è facile intuire, i tempi di compilazione delle lambda expression e di reflection sugli anonymous objects introducono a run-time delle latenze che rallentano sensibilmente la generazione delle URL (fino ad un ordine di grandezza!) rispetto all’esecuzione su creazioni dirette di &lt;span&gt;&lt;font color="#2b91af"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.routing.routevaluedictionary.aspx"&gt;RouteValueDictionary&lt;/a&gt;&lt;/font&gt;&lt;/span&gt;. Contrariamente, dal punto di vista dello sviluppo, proprio l’ultimo metodo è preferibile per il type checking a compile-time. &lt;/p&gt;
&lt;p&gt;           &lt;br /&gt;
&lt;font size="3"&gt;&lt;strong&gt;Note di configurazione&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;In quest’ultima parte del post vorrei semplicemente ricordare delle semplici accortezze che però sono fondamentali per rendere più performante un’ applicazione ASP.NET.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Impostare &lt;font face="Calibri"&gt;&lt;span class="code-keyword1"&gt;&lt;span style="line-height: 13pt;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size: 11pt;"&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;font style="font-size: 11pt;"&gt;&lt;span class="code-leadattribute1"&gt;&lt;span style="line-height: 13pt;"&gt;&lt;font color="#800000"&gt;compilation&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;span style="line-height: 13pt;"&gt;&lt;font style="font-size: 11pt;"&gt; &lt;span class="code-attribute1"&gt;&lt;font color="#ff0000"&gt;debug&lt;/font&gt;&lt;/span&gt;&lt;span class="code-keyword1"&gt;&lt;font color="#0000ff"&gt;="false"&lt;/font&gt;&lt;/span&gt; &lt;/font&gt;&lt;span class="code-keyword1"&gt;&lt;font color="#0000ff" style="font-size: 11pt;"&gt;/&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt; nel web.config della nostra applicazione nell’ambiente di produzione, in modo tale che il codice venga eseguito più velocemente.               &lt;br /&gt;
    &lt;/li&gt;
    &lt;li&gt;Rimuovere i moduli HTTP che non sono utilizzati. Nel machine.config o nel root-level web.config del framework troviamo una &lt;a href="http://msdn.microsoft.com/en-us/library/9b9dh535.aspx"&gt;configurazione di default&lt;/a&gt; che specifica il caricamento di diversi moduli che invece potremmo non usare nella nostra applicazione. Nel web.config possiamo quindi esplicitare l’esclusione dei moduli di cui non abbiamo bisogno dalla pipeline di ASP.NET (sia classica che integrata), facendo attenzione a non rompere le dipendenze tra i vari moduli.               &lt;br /&gt;
    &lt;br /&gt;
    (Pipeline classica)
    &lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;httpModules&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;                  &lt;br /&gt;
    &lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;      &amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;remove&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#ff0000"&gt;name&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt;Session&lt;/font&gt;&lt;/span&gt;"&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;font color="#0000ff"&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;                       &lt;br /&gt;
    &lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font color="#a31515"&gt;remove&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#ff0000"&gt;name&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt;WindowsAuthentication&lt;/font&gt;&lt;/span&gt;"&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;font color="#0000ff"&gt;&lt;span&gt; /&amp;gt;                        &lt;br /&gt;
    &lt;font face="Consolas"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;      &amp;lt;&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#a31515"&gt;remove&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt; &lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#ff0000"&gt;name&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;=&lt;/font&gt;&lt;/span&gt;"&lt;span&gt;&lt;font color="#0000ff"&gt;PassportAuthentication&lt;/font&gt;&lt;/span&gt;"&lt;/font&gt;&lt;font face="Consolas"&gt;&lt;font color="#0000ff"&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/font&gt;&lt;/font&gt;                         &lt;br /&gt;
          ...      &lt;/span&gt;&lt;span&gt;            &lt;/span&gt;                      &lt;br /&gt;
    &lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;/font&gt;&lt;span&gt;&lt;font color="#a31515"&gt;httpModules&lt;/font&gt;&lt;/span&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;&amp;gt;                        &lt;br /&gt;
    &lt;br /&gt;
    &lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;(Per la pipeline integrata il discorso è analogo. Basta posizionarsi nella sezione &lt;em&gt;system.webServer\modules)&lt;/em&gt;.&lt;/p&gt;
    &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;HTH&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:00aaae71-a891-4c99-9123-52341933fea6" style="margin: 0px; padding: 0px; float: none; display: inline;"&gt;Tag di Technorati: &lt;a rel="tag" href="http://technorati.com/tags/MVC"&gt;MVC&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/ASP.NET"&gt;ASP.NET&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/Performance"&gt;Performance&lt;/a&gt;&lt;/div&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/99616.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2011/01/11/migliorare-le-performance-di-unapplicazione-asp.net-mvc.aspx</guid>
            <pubDate>Tue, 11 Jan 2011 21:31:54 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2011/01/11/migliorare-le-performance-di-unapplicazione-asp.net-mvc.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/99616.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/99616.aspx</trackback:ping>
        </item>
        <item>
            <title>[ASP.NET MVC 2] Controller asincroni</title>
            <link>http://blogs.ugidotnet.org/dsantarelli/archive/2010/10/12/asp.net-mvc-2-controller-asincroni.aspx</link>
            <description>&lt;p&gt;Una feature molto importante del framework ASP.NET MVC ha a che vedere con la capacità di gestire operazioni asincrone a livello di controller. Di fatto il movente è lo stesso che si trova dietro le &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/magazine/cc163725.aspx"&gt;Asynchronous Pages in ASP.NET 2.0&lt;/a&gt;, ovvero evitare che si verifichino condizioni di thread starvation nella nostra Web Application per poi vedersi ritornare un simpatico status code 503 (Server too busy). Come sappiamo, quando una richiesta viene ricevuta dal Web Server, il processamento viene affidato ad un thread del threadpool dell’applicazione. In uno scenario sincrono, tale thread rimane in vita fintantoché non vengono effettuate tutte le operazioni previste.     &lt;br /&gt;
Quindi, potremmo dire a grandi linee che la pipeline asincrona è preferibile in scenari in cui la logica prevede colli di bottiglia che si formano in corrispondenza di operazioni bloccanti, a causa di latenze non legate strettamente al tempo di CPU (es. chiamate ad un WS).     &lt;br /&gt;
Partendo dal presupposto che una richiesta asincrona possiede lo stesso tempo di esecuzione di una richiesta sincrona, minimizzare il numero di thread in attesa di operazioni bloccanti è una pratica molto apprezzata dal Web Server quando una Web Application viene letteralmente bombardata da centinaia di richieste concorrenti.     &lt;br /&gt;
&lt;br /&gt;
Vediamo ora un esempio molto banale di controller asincorno, in cui l’action &lt;em&gt;List&lt;/em&gt; è stata creata secondo il pattern asincrono per gestire chiamate “lunghe” ad un Web Service:&lt;/p&gt;
&lt;font face="Courier New"&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;font face="Courier New"&gt;&lt;span lang="EN-US" style="font-family: courier new;"&gt;&lt;font color="#0000ff"&gt;&lt;font style="font-size: 8pt;"&gt;public&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: courier new;"&gt;&lt;font style="font-size: 8pt;"&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;class&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;CustomersController&lt;/font&gt;&lt;/span&gt; : &lt;/font&gt;&lt;span&gt;&lt;font color="#2b91af" style="font-size: 8pt;"&gt;AsyncController&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;font style="font-size: 8pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;font style="font-size: 8pt;"&gt;[&lt;span&gt;&lt;font color="#2b91af"&gt;AsyncTimeout&lt;/font&gt;&lt;/span&gt;(10000)]&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt;&lt;/span&gt; ListAsync()&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;AsyncManager.OutstandingOperations.Increment();&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#2b91af"&gt;Task&lt;/font&gt;&lt;/span&gt;.Factory.StartNew(() =&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;       &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;try&lt;/font&gt;&lt;/span&gt; { AsyncManager.Parameters[&lt;span&gt;&lt;font color="#a31515"&gt;"result"&lt;/font&gt;&lt;/span&gt;] = &lt;span&gt;&lt;font color="#0000ff"&gt;new&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;MyServiceClient&lt;/font&gt;&lt;/span&gt;().GetCustomers(); }&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;       &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;catch&lt;/font&gt;&lt;/span&gt; (&lt;span&gt;&lt;font color="#2b91af"&gt;Exception&lt;/font&gt;&lt;/span&gt; ex) { ... }&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;       &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;finally&lt;/font&gt;&lt;/span&gt; { AsyncManager.OutstandingOperations.Decrement(); }&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;font style="font-size: 8pt;"&gt; &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;public&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;ActionResult&lt;/font&gt;&lt;/span&gt; ListCompleted(&lt;span&gt;&lt;font color="#2b91af"&gt;List&lt;/font&gt;&lt;/span&gt;&amp;lt;&lt;span&gt;&lt;font color="#2b91af"&gt;Customer&lt;/font&gt;&lt;/span&gt;&amp;gt; result)&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;return&lt;/font&gt;&lt;/span&gt; View(&lt;span&gt;&lt;font color="#a31515"&gt;"List"&lt;/font&gt;&lt;/span&gt;, result);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;}            &lt;br /&gt;
&lt;br /&gt;
   ...&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;span&gt;&lt;font face="Courier New"&gt;&lt;font style="font-size: 8pt;"&gt;       &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;protected&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;override&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#0000ff"&gt;void&lt;/font&gt;&lt;/span&gt; OnException(&lt;span&gt;&lt;font color="#2b91af"&gt;ExceptionContext&lt;/font&gt;&lt;/span&gt; filterContext)&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;if&lt;/font&gt;&lt;/span&gt; (filterContext.Exception &lt;span&gt;&lt;font color="#0000ff"&gt;is&lt;/font&gt;&lt;/span&gt; &lt;span&gt;&lt;font color="#2b91af"&gt;TimeoutException&lt;/font&gt;&lt;/span&gt;)&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;{&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;       &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;filterContext.Result = RedirectToAction(&lt;span&gt;&lt;font color="#a31515"&gt;"TryAgainLater"&lt;/font&gt;&lt;/span&gt;);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;       &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;filterContext.ExceptionHandled = &lt;span&gt;&lt;font color="#0000ff"&gt;true&lt;/font&gt;&lt;/span&gt;;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;}&lt;/font&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;            &lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;     &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;&lt;span&gt;&lt;font color="#0000ff"&gt;base&lt;/font&gt;&lt;/span&gt;.OnException(filterContext);&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;font face="Courier New"&gt;&lt;span&gt;&lt;font style="font-size: 8pt;"&gt;   &lt;/font&gt;&lt;/span&gt;&lt;font style="font-size: 8pt;"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;span lang="EN-US" style="font-family: ;"&gt;&lt;span&gt;&lt;font face="Courier New"&gt;&lt;font style="font-size: 8pt;"&gt;    &lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal;"&gt;&lt;font face="Courier New"&gt;&lt;span style="font-family: ;"&gt;&lt;font style="font-size: 8pt;"&gt;}&lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;
&lt;/font&gt;  &lt;br /&gt;
&lt;p&gt;Alcune importanti osservazioni:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Un controller asincrono deve ereditare la classe &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.mvc.asynccontroller.aspx"&gt;AsyncController&lt;/a&gt;. (Gli action methods sincroni sono comunque supportati) &lt;/li&gt;
    &lt;li&gt;Il nome del metodo del controller che scatena l’operazione asincrona deve essere seguito dal suffisso “&lt;em&gt;Async&lt;/em&gt;”. &lt;/li&gt;
    &lt;li&gt;Il nome del metodo del controller che viene invocato dal framework quando l’operazione asincrona viene completata deve essere seguito dal suffisso “&lt;em&gt;Completed&lt;/em&gt;” &lt;/li&gt;
    &lt;li&gt;Sebbene il pattern asincrono consiste di due metodi, l’invocazione da browser segue la stessa route che si utilizzerebbe per le action sincrone ( …/Customers/List ) &lt;/li&gt;
    &lt;li&gt;La proprietà &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.mvc.async.asyncmanager.parameters.aspx"&gt;AsyncManager.Parameters&lt;/a&gt; è un &lt;em&gt;IDictionary&amp;lt;string,object&amp;gt;&lt;/em&gt; che permette di definire i parametri che vengono passati al metodo xxxCompleted, evitando allo sviluppatore l’onere di definire delle variabili a livello di classe che siano visibili da entrambi i metodi &lt;em&gt;xxxAsync&lt;/em&gt; e &lt;em&gt;xxxCompleted&lt;/em&gt;. Occorre inoltre porre attenzione al nome che si assegna alle key dei parametri. Essi devono infatti corrispondere a quelli dichiarati dal metodo &lt;em&gt;xxxCompleted.&lt;/em&gt; &lt;/li&gt;
    &lt;li&gt;I metodi &lt;em&gt;AsyncManager.OutstandingOperations.Increment(…)&lt;/em&gt; e &lt;em&gt;AsyncManager.OutstandingOperations.Decrement()&lt;/em&gt; sono necessari rispettivamente per determinare il numero di operazioni asincrone che il controller deve ancora completare e che ha completato. Attenzione a non ometterli ed a gestirli in modo consistente!!! &lt;/li&gt;
    &lt;li&gt;L’attributo &lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.mvc.asynctimeoutattribute.aspx"&gt;AsyncTimeout&lt;/a&gt; specificato a livello di metodo &lt;em&gt;xxxAsync&lt;/em&gt; è utile per definire un timeout per le operazioni a lunga latenza (default: 45 secondi). Se lo si vuole eliminare si può utilizzare il filtro [&lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/system.web.mvc.noasynctimeoutattribute.aspx"&gt;NoAsyncTimeout&lt;/a&gt;] oppure l’equivalente &lt;em&gt;[AsyncTimeout(Timeout.Infinite)]&lt;/em&gt;. Se invece lo si vuole gestire per fornire un feedback diverso rispetto al global exception handler di ASP.NET, è possibile svilupparsi un exception filter personalizzato oppure semplicemente fare l’override del metodo &lt;em&gt;OnException(…)&lt;/em&gt; del controller, in modo da gestire l’eccezione in modo custom (come in questo caso). &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Non è tutto oro ciò che luccica…&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;I controller asincroni sono significativamente più complessi rispetto a quelli sincroni, oltre ad essere difficilmente testabili. &lt;/li&gt;
    &lt;li&gt;Non ha alcun senso utilizzare controller asincroni se si vogliono semplicemente eseguire dei task paralleli legati alle prestazioni della CPU. &lt;/li&gt;
    &lt;li&gt;Occorre assicurarsi che il nostro Web Server sia opportunamente configurato per beneficiare della gestione asincrona delle richieste web: ad esempio, se usiamo IIS7 dobbiamo configurare correttamente il valore della proprietà &lt;em&gt;MaxConcurrentRequestsPerCPU&lt;/em&gt; nella sezione &lt;a target="_blank" href="http://msdn.microsoft.com/it-it/library/dd560842.aspx"&gt;&amp;lt;applicationPool&amp;gt;&lt;/a&gt; di &amp;lt;system.web&amp;gt;, impostandolo ad un valore sufficientemente alto. &lt;/li&gt;
&lt;/ul&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4235d7fc-f7c1-4d7f-9276-86199baa1102" style="margin: 0px; padding: 0px; float: none; display: inline;"&gt;Tag di Technorati: &lt;a rel="tag" href="http://technorati.com/tags/AsyncController"&gt;AsyncController&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/ASP.NET"&gt;ASP.NET&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/MVC"&gt;MVC&lt;/a&gt;&lt;/div&gt;&lt;img src="http://blogs.ugidotnet.org/dsantarelli/aggbug/99343.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Dario Santarelli</dc:creator>
            <guid>http://blogs.ugidotnet.org/dsantarelli/archive/2010/10/12/asp.net-mvc-2-controller-asincroni.aspx</guid>
            <pubDate>Tue, 12 Oct 2010 21:00:57 GMT</pubDate>
            <comments>http://blogs.ugidotnet.org/dsantarelli/archive/2010/10/12/asp.net-mvc-2-controller-asincroni.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/dsantarelli/comments/commentRss/99343.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/dsantarelli/services/trackbacks/99343.aspx</trackback:ping>
        </item>
    </channel>
</rss>