Gli Action Filter ed i Global Filter di ASPNET MVC

Già dalla prima release di ASPNET MVC è stato introdotto il concetto di Action Filter, ossia un attributo che può decorare sia una singola Action o che addirittura un intero Controller.

Lo scopo di questi Filter è quello di aggiungere funzionalità che spesso ci troveremmo a scrivere con molta frequenza, o addirittura per ogni singola chiamata; per capire il concetto è sufficiente pensare ad una serie di Action che dovranno essere accessibili soltanto agli utenti loggati. Se provate ad immaginare questo scenario, un possibile risultato potrebbe essere questo:

public class HomeController : Controller {
    public ActionResult Index ( ) {
        if(!HttpContext.User.Identity.IsAuthenticated)
            Redirect ( "/Login" );

        //TODO: Fai qualcosa

        return View ( );
    }

    public ActionResult Products ( ) {
        if (!HttpContext.User.Identity.IsAuthenticated)
            Redirect ( "/Login" );

        //TODO: Fai qualcosa

        return View ( );
    }

    public ActionResult Details ( ) {
        if (!HttpContext.User.Identity.IsAuthenticated)
            Redirect ( "/Login" );

        //TODO: Fai qualcosa

        return View ( );
    }
}

Come si può notare in tutte e tre le Action c’è un blocco di codice ripetuto che non fa altro che verificare che l’utente corrente sia autenticato e, nel caso non lo sia, lo reindirizza alla pagina di Login. Lo scopo degli Action Filter è di racchiudere tutta la logica che può essere comune alle Action, indipendentemente dal Binder in entrata e da ciò che la Action stessa deve fare, permettendoci così di sostituire tutte quelle righe di codice con un semplice attributo. Di fatto l’esecuzione del Filter avviene prima dell’esecuzione del codice presente all’interno della Action.
Lo snippet seguente mostra le stesse identiche Action dell’esempio precedente, ma con l’utilizzo degli Action Filter:

public class HomeController : Controller {
    [Authorize]
    public ActionResult Index ( ) {
        //TODO: Fai qualcosa

        return View ( );
    }

    [Authorize]
    public ActionResult Products ( ) {
        //TODO: Fai qualcosa

        return View ( );
    }

    [Authorize]
    public ActionResult Details ( ) {
        //TODO: Fai qualcosa

        return View ( );
    }
}

Oppure a livello di controller

[Authorize]
public class HomeController : Controller {
    public ActionResult Index ( ) {
        //TODO: Fai qualcosa

        return View ( );
    }

    public ActionResult Products ( ) {
        //TODO: Fai qualcosa

        return View ( );
    }
    
    public ActionResult Details ( ) {
        //TODO: Fai qualcosa

        return View ( );
    }
}

All’interno di MVC esistono già diversi Action Filter, come l’Authorize mostrato sopra, oltre ad altri come OutputCache, HandleError, etc; inoltre nulla ci vieta di crearne dei nostri custom, come mostrato in un mio precedente post (qui).

L’ultima release di MVC (la 3, di cui ho già parlato in parte qui) offre la possibilità di registrare i controlli in modalità globale per tutta l’applicazione, evitandoci così il noioso copia ed incolla per tutti i controller dell’applicazione.

Per far ciò è necessario registrare l’Action Filter nel global.asax, come mostrato di seguito:

protected void Application_Start ( ) {
    AreaRegistration.RegisterAllAreas ( );

    GlobalFilters.Filters.Add ( new HandleErrorAttribute ( ) );
    GlobalFilters.Filters.Add ( new AuthorizeAttribute ( ) );

    RegisterRoutes ( RouteTable.Routes );
}

Non male direi.

Ciauz


Comments