Gestire HttpRequestValidationException in ASP.NET MVC

Print Content | More

Chi lavora con le applicazioni web si sarà sicuramente imbattuto nell’eccezione HttpRequestValidationException scatenata dall’engine di ASP.NET quando un client cerca di effettuare il submit di informazioni potenzialmente pericolose, aka codice html, verso il server.
Personalmente ritengo questa una comodissima feature in quanto ci consente di “alleggerire” la nostra applicazione nell’analisi dei dati in ingresso e demandare il tutto ad ASP.NET; al contrario, se si vuole gestire questa casistica secondo dei propri requirements, è possibile disattivarla e prendersi carico e responsabilità del fatto che ciò che arriverà dal client non è stato validato da nessuno.

Dando per assodato che, dal mio punto di vista, questa funzione dovrebbe rimanere abilitata, quello che vorrei specificare in questo post è come mostrare all’utente un messaggio “friendly” che lo invita ad inserire del plaintext nel campo di input. L’idea è nata analizzando il log del mio blog, in cui ho trovato una miriade di tentativi di commenti che cercavano di inserire link (praticamente tutto spam), ma senza successo grazie a questo blocco.

Questo è possibile in diversi modi, come con l’utilizzo di httpmodule, applicationError, etc., ma in applicazioni MVC preferisco utilizzare il meno possibile HttpModule (vuoi perchè in IntegratedMode passa veramente di tutto) e gestire la cosa dal controller.
In Dexter ho un ControllerBase da cui ereditano tutti i controller, dove, oltre ad esporre delle ActionResult custom, ho la gestione dei log per ciò che riguarda la parte di MVC, in soldoni ho l’override del metodo OnException dove butto dentro la mia logica di logging, etc.

Quando una qualsiasi eccezione riguardante una richiesta MVC viene sollevata dal framework, si può essere certi che verrà intercettata e verrà invocato quel metodo, permettendoci di gestirla a nostro piacimento.

protected override void OnException(ExceptionContext filterContext)
{
    HttpException httpException = filterContext.Exception as HttpException;

    if (httpException is HttpRequestValidationException)
    {
        Logger.Info ( httpException.Message , httpException );

        var currentUrl = filterContext.RequestContext.HttpContext.Request.Url.AbsolutePath;

        filterContext.ExceptionHandled = true;

        filterContext.Result =  RedirectToAction("HttpRequestValidation", "Errors", new
                                                                    {
                                                                 aspxerrorpath = currentUrl
                                                                    });
    } else if (httpException != null && httpException.GetHttpCode() == 404)
        Logger.Info(httpException.Message, httpException);
    else if (filterContext.Exception is HttpAntiForgeryException)
        Logger.Info(filterContext.Exception.Message, filterContext.Exception);
    else
        Logger.Error("Generic Exception", filterContext.Exception);
}

Come potete vedere non è nulla di fantascientifico ed è più o meno quello che si andrebbe a fare con un’applicazione WebForm classica, fatta eccezione per l’utilizzo della proprietà ExceptionHandled, che notifica a MVC che siamo noi a prenderci in carico il Result da quel momento in poi, e di fatto subito dopo si va ad effettuare un redirect.

Il risultato è questo.


MVC , Exception Handling

0 comments

Habemus MVC3 (preview 1)

Print Content | More

L’annuncio arriva direttamente dal blog di Scott Guthrie, anche se il download era apparso sui server Microsoft già da alcune ore: sta di fatto che MVC 3 Preview 1 è stato rilasciato, e lo potete scaricare direttamente qui.
Anche la versione 3 sembra percorrere quanto già fatto dalla versione 2, ossia evolvere quanto di già buono c’è senza stravolgere la struttura, quindi non aspettatevi di trovare grandissimi cambiamenti all’interno di questa release.

Tra le novità è stato incluso Razor, un view engine “csharp like” che va ad affiancarsi al view engine già presente, permettendo così di avere View scritte con differenti sintassi; un’altra novità molto interessante è la presenza dell’IServiceLocator, che personalmente ritenevo una mancanza in MVC2 (in dexter abbiamo implementato un qualcosa di simile).
In linea di massima tutta la parte di Dependency Injection è stata migliorata e di fatto ora è possibile andare a “giocare” con controller, viewengine, views, validation providers, model meta data provider, model binder, e chi più ne ha più ne metta.

Sono presenti anche altre novità di minor rilievo come ViewData dinamico, che sfrutta la keyword dynamics di c# 4 e di conseguenza vincola l’utilizzo di MVC3 all’ultima release del .NET Framework.

Direi che di argomenti e spunti per poter parlare e provare MVC3 ce ne sono, e sicuramente un confronto di Razor con Spark non tarderà ad arrivare.

Ciauz


MVC , News

1 comments

Slide della mia sessione all’evento GroundZero di DotNetLombardia

Print Content | More

Da pochi giorni si è concluso l’evento GroundZero di DotNetLombardia, dove ho avuto l’opportunità di parlare un po’ delle novità introdotte con il .NET Framework 4.0 per il mondo web, quindi di ASP.NET, MVC2 ed AJAX.
Ringrazio tutta l’organizzazione e le persone presenti per aver scelto di passare una passare una giornata a parlare di tecnologia.

Purtroppo  non ho avuto modo di assistere a tutte le sessioni della giornata (molto bravo Federico); in particolar modo mi avrebbe fatto piacere assistere la sessione del mio super Desk Neighbor Matteo e di Giuseppe che sicuramente sarebbe riuscito a farmi capire un po’ Sharepoint.

Il download delle slide è disponibile qui


Eventi , DotNetLombardia

2 comments

Where The Hell is Dexter

Print Content | More

È un po’ che non faccio un post su Dexter, ma questo non vuol dire che il progetto è fermo, anzi: ci stiamo lavorando tanto e nel dev team sono apparsi nomi nuovi, alcuni anche di un certo peso, il che mi fa molto piacere.
Detto ciò, ieri sera ho aggiornato la versione attuale del mio blog all’ultima release della trunk, che apporta una serie di migliorie ed ovviamente un gran numero di nuove features.

In primis è stato fortemente potenziato il supporto per Windows Live Writer che ora gestisce nativamente Tagging (con intellisense), Categorie Multiple (con sottocategorie), Abstract, Slug Customizzati e, dulcis in fundo, offre la possibilità di creare dinamicamente le proprie pagine (la mia pagina about è stata creata con WLW) con la possibilità di avere un vero e proprio Tree di pagine (maggiori info qui).

Alcuni screenshot:

WIndows Live Writer 001WIndows Live Writer 002WIndows Live Writer 003WIndows Live Writer 004


Per chi è un fan di WLW i complimenti vanno al buon Alessandro che ha dedicato molto del suo tempo libero a realizzare questa parte.
Oltre a questo, da come si era intuito dai miei ultimi post, è possibile realizzare skin anche utilizzando SparkViewEngine; ovviamente rimane la possibilità di scriverle in maniera “classica” o, se si preferisce, mista.
L’attuale skin è il porting della precedente in Spark e sembra girare bene, a dimostrazione dell’ottimo prodotto.

Di migliorie ce ne sono davvero tante, dalle notifiche con template, incluse di master page e localizzazione, fino ad arrivare ai post schedulati, autochiusura dei commenti per i post più vecchi di x giorni, OpenSearch, plugin, etc.
Importanti novità sono “in canna”: nelle prossime settimane prenderà luce la prima beta dotata di un sistema di autoinstallazione, configurazione ed upgrade automatico, e, da lì a breve, si aggiungeranno molte altre cose che ora non posso svelare.

Per chi fosse interessato ad un’eventuale migrazione è pronto un tool per l’import da Wordpress, e a breve da BlogML e RSS.

Che dire, un mega grazie a tutti quelli che mi hanno scritto e supportato in questa pazza avventura.
Ciauz


Dexter , MVC , Asp

3 comments

Intervista per Microsoft Feeds

Print Content | More

image

Ieri è stata pubblicata una mia intervista per Microsoft Feed, per chi fosse interessato alla mia mini storiella potete dare un occhio qui.

Ciauz


Microsoft Feed

0 comments

SparkViewEngine: Iterazioni

Print Content | More

Nel post precedente ho mostrato come è possibile ridurre il numero di righe di codice presenti all’interno della skin quando ci si trova a dover gestire dei blocchi di if per la visualizzazione di porzioni di Html. Ovviamente all’interno delle nostre Views non ci troviamo soltanto ad utilizzare i vari if/elseif/else, ma sicuramente andremo a creare delle iterazioni che ci permettono di mostrare un set di contenuti, come potrebbe essere l’elenco delle ultime news.

L’approccio è lo stesso, ed in questi due blocchi di codice (engine classic e spark) possiamo notare come è possibile evitare la sintassi di apertura e di chiusura del ciclo:

<%for (int i = 0; i < Model.Categories.Count; i++){%>
    <li class="category">
        <%= Model.Categories[i].Name%>
    </li>
<%}%>
<li class="category" each="var Category in Model.Categories">
    ${Category.Name}
</li>

Ovviamente volendo è possibile usare una sintassi leggermente differente, e quindi senza l’attributo each per un tag container: in questo caso è sufficiente utilizzare il tag for, come mostrato di seguito:

<for each="var Category in Model.Categories">
    <li class="category">
        ${Category.Name}
    </li>
</for>

Come potete vedere in questa situazione, anche se non si ha un vantaggio nel numero di righe scritte, si ha comunque un vantaggio in leggibilità del codice.

Sicuramente in alcuni casì c’è però la necessità di essere a conoscenza dell’esatta posizione in cui ci si trova all’interno del ciclo,  del numero totale di elementi, oppure di sapere se si è all’inizio o alla fine dello stesso: il problema è risolto grazie a Spark, che mette a disposizione, tramite un’apposita name convention, delle proprietà che ci restituiscono queste informazioni, come mostrato di seguito:

<for each="var Category in Model.Categories">
    ItemIndex = ${CategoryIndex}
    TotalItems = ${CategoryCount}
    IsFirstItem = ${CategoryIsFirst}
    IsLastItem = ${CategoryIsLast}
</for>

Come potete vedere basta aggiungere in coda all’item corrente (category nell’esempio) un suffisso, il resto lo fa Spark.

Enjoy it.


SparkViewEngine , ViewEngine , MVC

0 comments

Disponibile il mio webcast su ASP.NET MVC 2: security

Print Content | More

Ieri è stato pubblicato un mio webcast su MVC intitolato “ASP.NET MVC 2: Security” sul portale BEIT di Microsoft.

Come sempre per feedback, domande, etc mi trovate qui.

image


MVC , Webcast

0 comments

ASP.NET 4.0, MVC2 e jQuery…what else?

Print Content | More

GroudZeroEventBrite_thumb


Il 22 Luglio si terrà Ground Zero, ovvero il primo evento “di lancio” di DotNetLombardia: sarà un’intera giornata di approfondimento dedicata alle più recenti tecnologie, ed io avrò la fortuna di tenere una sessione riguardante il mondo web.

Sono molto felice di partecipare come speaker a questo evento, la cui agenda è sicuramente interessante; in più c’è il debutto del mio desk neighbor Matteo, che avrà modo di parlare del mondo mobile e di Windows Phone.

Direi che ora è tempo di preparare un po’ di materiale in quanto gli argomenti sono molti e tutti interessanti: come preannuncia il titolo di questo post mostrerò un cocktail delle novità riguardanti lo sviluppo web con il .NET Framework 4.0.

L’agenda è disponibile qui, mentre la registrazione qui.
Non mancate!

Ciauz


Eventi , DotNetLombardia

2 comments

SparkViewEngine: If, else, elseif

Print Content | More

Una delle cose che trovo più belle di Spark è la possibilità di ridurre, a volte anche dimezzare, il numero di righe di codice presenti all’interno delle nostre View.

Fortunatamente con MVC molta della logica non esiste più, a parte quella riguardante la visualizzazione o meno di un blocco di html, il cambiamento di un css in base ad una condizione, oppure l’iterazione di una collection; in soldoni non dovremmo avere molto codice all’interno se non delle if/else, dei for.

Supponiamo di avere un codice come il seguente:

<%if (Model.RecentPost.Count > 0){%>
<li>
   something
</li>
<%}%>

in Spark possiamo rimuovere due righe, la prima di apertura della if e quella di chiusura, impostando la condizione direttamente nell’attributo del tag da mostrare, come da snippet seguente:

<li if="Model.RecentPost.Count > 0">
    something
</li>

Ovviamente, se la if non deve racchiudere un solo tag ma più blocchi di tag non annidati, si può utilizzare l’apposita sintassi di Spark che, come potete vedere dall’esempio seguente, è molto simile al codice HTML:

<if confition="Model.RecentPost.Count > 0">
    <li>something</li>
    <li>something 1</li>
    <li>something 2</li>
</if>

Anche le altre condizioni else ed elseif funzionano allo stesso modo:

<li if="Model.RecentPost.Count > 0">something</li>
<li elseif="Model.RecentPost.Count == 0">something 1</li>
<else>
    <li>something 2</li>
</else>

Oppure:

<if condition="Model.RecentPost.Count > 0">
   <li>something</li>
</if>
<else if="Model.RecentPost.Count == 0">
  <li>something 2</li>
</else>
<else>
  <li>something 3</li>
</else>

Enjoy Spark


SparkViewEngine , MVC , ViewEngine

0 comments

Gestire le risorse con SparkViewEngine

Print Content | More

Già nel post precedente ho introdotto SparkViewEngine; in questo voglio mostrare un’interessante feature che apre diversi scenari di mantenibilità e di “servizio”, come nel caso di Dexter che mostrerò più avanti.

Sicuramente ci sarà capitato molto spesso di dover “hostare” le nostre applicazioni all’interno di una virtual directory, e magari di doverle spostare successivamente sulla root di un sito e viceversa: spesso questo risulta scomodo in quanto può comportare alcune modifiche ai percorsi dei file di risorse (immagini, css, javascript, etc). Se proviamo a guardare il lato pratico, un codice html simile a questo:

<link type="text/css" rel="stylesheet" href="/Styles/Site.css" />

non sarebbe più valido nel caso il sito fosse spostato all’interno di una virtual directory, e dovrebbe diventare una cosa del tipo:

<link type="text/css" rel="stylesheet" href="/MyVirtualDirectory/Styles/Site.css" />

 

Ovviamente il problema è risolvibile sfruttando un helper che effettua il resolve dell’url, con il conseguente svantaggio di aggiungere codice all’interno del markup, rendendo difficile un eventuale refactoring; a questo si aggiunge la perdita in leggibilità del codice html. Un’altra soluzione è far gestire i percorsi delle risorse a Spark (devo dire che lo fa egregiamente e con estrema semplicità) : in primis è necessario modificare il web.config aggiungendo la sezione di Spark, come mostrato di seguito:

    <section name="spark" type="Spark.Configuration.SparkSectionHandler, Spark" requirePermission="false"/>
</configSections>

<spark>
    <compilation debug="false"/>
    <pages automaticEncoding="true">
        <namespaces>
            <add namespace="System" />
            <add namespace="System.Web" />
            <add namespace="System.Web.Mvc" />
            <add namespace="System.Web.Mvc.Ajax" />
            <add namespace="System.Web.Mvc.Html" />
            <add namespace="System.Web.Routing" />
            <add namespace="System.Linq" />
        </namespaces>
        <resources>
            <add match="~/Scripts" location="/Resource/Scripts" />
            <add match="~/Styles" location="/Resource/Styles" />
            <add match="~/Images" location="/Resource/Images" />
            <add match="~/Media" location="/Resource/Media" />
        </resources>
    </pages>
</spark>

Come potete intuire la sezione resource è quella più interessante, e ci permette di specificare dove sono presenti i files delle risorse: quindi, lato view, è sufficiente utilizzare il tilde per indicare il percorso iniziale dell’applicativo, poi ci penserà spark in fase di rendering a sostituirlo con quanto specifica nel file di configurazione.
Se proviamo a renderizzare questo codice html con i settaggi sopra specificati, il rendering finale dovrebbe essere questo:

<link type="text/css" rel="stylesheet" href="~/Styles/Site.css" />

<link type="text/css" rel="stylesheet" href="/Resouce/Styles/Site.css" />

 

Ovviamente questo può aprire un ulteriore scenario, ossia offrire la possibilità a chi sviluppa la parte html di utilizzare alcune CDN (google, Microsoft, etc) senza doverne conoscere il percorso; di fatto, chi vuole sviluppare una skin per dexter e vuole utilizzare la cdn di Microsoft per jQuery, può semplicemente scrivere questo:

<script src="~/Scripts/CDN/jQueryTools/1.2.2/jquery.tools.min.js" type="text/javascript" language="javascript"></script>

Così facendo si può cambiare in un qualsiasi momento la CDN da utilzzare, o scegliere di hostare il file con la libreria su un proprio server.
Di seguito riporto il blocco di configurazione di spark in dexter, che mostra le varie CDN supportate:

<spark>
    <compilation debug="false"/>
    <pages automaticEncoding="true">
        <namespaces>
            <add namespace="System" />
            <add namespace="System.Web" />
            <add namespace="System.Web.Mvc" />
            <add namespace="System.Web.Mvc.Ajax" />
            <add namespace="System.Web.Mvc.Html" />
            <add namespace="System.Web.Routing" />
            <add namespace="System.Linq" />
            <add namespace="Dexter.Web.Site.Models.Blog" />
            <add namespace="System.Collections.Generic" />
            <add namespace="Dexter.Web.Mvc.Helpers" />
            <add namespace="Dexter.Core.Configuration" />
            <add namespace="Dexter.Core.Concrete" />
            <add namespace="Dexter.Web.Mvc.Controls" />
        </namespaces>
        <resources>
            <add match="~/Scripts/CDN/Microsoft" location="http://ajax.microsoft.com/ajax"/>                 <!-- http://www.asp.net/ajaxlibrary/cdn.ashx -->
            <add match="~/Scripts/CDN/Google" location="http://ajax.googleapis.com/ajax/libs"/>                 <!-- http://code.google.com/apis/ajaxlibs/documentation/#AjaxLibraries -->
            <add match="~/Scripts/CDN/jQueryTools" location="http://cdn.jquerytools.org"/>                    <!-- http://flowplayer.org/tools/download/index.html -->
            <add match="~/Scripts" location="~/Scripts" />
            <add match="~/Styles" location="~/Styles" />
            <add match="~/Images" location="~/Images" />
            <add match="~/Media" location="~/Media" />
        </resources>
    </pages>
</spark>

Ciauz


SparkViewEngine , Dexter , ViewEngine

3 comments