Gestire HttpRequestValidationException in ASP.NET MVC

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.


Comments