Esporta (0) Stampa
Espandi tutto
Il presente articolo è stato tradotto manualmente. Passare il puntatore sulle frasi nell'articolo per visualizzare il testo originale.
Traduzione
Originale

Creazione di filtri azione personalizzati

Gli utilizzi possibili dei filtri azione sono svariati così come le azioni alle quali possono essere applicati. Tra gli utilizzi possibili dei filtri azione sono inclusi i seguenti:

  • Registrazione allo scopo di tenere traccia delle interazioni dell'utente.

  • "Anti-image-leeching", una funzionalità che impedisce che le immagini vengano caricate nelle pagine che non fanno parte del sito.

  • Filtro tramite agente di ricerca Web per la modifica del comportamento dell'applicazione in base all'agente utente del browser.

  • Localizzazione per la configurazione delle impostazioni locali.

  • Azioni dinamiche per l'inserimento di un'azione in un controller.

Un filtro azioni viene implementato come classe Attribute che eredita da ActionFilterAttribute. ActionFilterAttribute è una classe astratta che dispone di quattro metodi virtuali di cui è possibile eseguire l'override: OnActionExecuting, OnActionExecuted, OnResultExecuting e OnResultExecuted. Per implementare un filtro azioni, è necessario eseguire l'override di almeno uno di questi metodi.

Il framework di MVC ASP.NET chiamerà il metodo OnActionExecuting del filtro azioni prima di chiamare qualsiasi metodo di azione contrassegnato con l'attributo di filtro dell'azione. In modo analogo, il framework chiamerà il metodo OnActionExecuted al completamento del metodo di azione.

Il metodo OnResultExecuting viene chiamato appena prima del richiamo dell'istanza ActionResult restituita dall'azione. Il metodo OnResultExecuted viene chiamato appena dopo l'esecuzione del risultato. Questi metodi sono utili per eseguire azioni quali la registrazione, la memorizzazione nella cache di output e così via.

Nell'esempio seguente viene illustrato un filtro azioni semplice che consente di registrare i messaggi di traccia prima e dopo la chiamata di un metodo di azione.


public class LoggingFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Trace.Write("(Logging Filter)Action Executing: " +
            filterContext.ActionDescriptor.ActionName);

        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Exception != null)
            filterContext.HttpContext.Trace.Write("(Logging Filter)Exception thrown");

        base.OnActionExecuted(filterContext);
    }
}


Ogni gestore eventi del controller per il filtro delle azioni accetta un oggetto di contesto come parametro. Nell'elenco seguente vengono illustrati i gestori eventi di filtro e il rispettivo tipo di contesto accettato.

Tutte le classi di contesto ereditano dalla classe ControllerContext e includono una proprietà ActionDescriptor. È possibile utilizzare la proprietà ActionDescriptor per identificare l'azione alla quale è attualmente applicato il filtro.

Le classi ActionExecutingContext e ResultExecutingContext contengono una proprietà Cancel che consente di annullare l'azione.

Le classi ActionExecutedContent e ResultExecutedContext contengono una proprietà Exception e una proprietà ExceptionHandled. Se la proprietà Exception è null, significa che non si è verificato alcun errore al momento dell'esecuzione del metodo di azione. Se la proprietà Exception non è null e il filtro è in grado di gestire l'eccezione, il filtro può gestire l'eccezione e quindi segnalare l'esecuzione di tale operazione impostando la proprietà ExceptionHandled su true. Anche se la proprietà ExceptionHandled è true, verrà chiamato il metodo OnActionExecuted o OnResultExecuted di qualsiasi filtro azioni aggiuntivo nello stack a cui verranno passate le informazioni sull'eccezione. Ciò rende possibili scenari quali la registrazione di un'eccezione da parte di un apposito filtro anche quando l'eccezione è stata gestita. In generale un filtro azioni non deve gestire un'eccezione a meno che l'errore sia specifico per tale filtro.

È possibile applicare un filtro di azione a tutti i metodi di azione necessari. Nell'esempio seguente viene illustrato un controller che contiene metodi di azione contrassegnati con un attributo di filtro dell'azione. In questo caso, tutti i metodi di azione nel controller richiameranno lo stesso filtro azioni.


[HandleError]
public class HomeController : Controller
{
    [LoggingFilter]
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        if (TempData.ContainsKey("Clicked"))
        {
            ViewData["Clicked"] = true;
        }
        else ViewData["Clicked"] = false;

        if ((Boolean)ViewData["Clicked"] == true)
        {
            ViewData["ClickMessage"] = "You clicked this button.";
            ViewData["Clicked"] = false;
        }

        return View();
    }

    [LoggingFilter]
    public ActionResult About()
    {
        return View();
    }

    [LoggingFilter]
    public ActionResult ClickMe()
    {
        TempData["Clicked"] = true;

        return RedirectToAction("Index");
    }
}


La classe Controller di MVC ASP.NET definisce i metodi OnActionExecuting e OnActionExecuted di cui è possibile eseguire l'override. Quando si esegue l'override di uno di questi metodi o di entrambi, la logica verrà eseguita prima o dopo tutti i metodi di azione di tale controller. Questa funzionalità è analoga ai filtri azione, sebbene l'ambito dei metodi venga definito dal controller.

Nell'esempio seguente vengono illustrati i metodi OnActionExecuting e OnActionExecuted a livello di controller che si applicano a tutti i metodi di azione nel controller.


[HandleError]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        if (TempData.ContainsKey("Clicked"))
        {
            ViewData["Clicked"] = true;
        }
        else ViewData["Clicked"] = false;

        if ((Boolean)ViewData["Clicked"] == true)
        {
            ViewData["ClickMessage"] = "You clicked this button.";
            ViewData["Clicked"] = false;
        }

        return View();
    }

    public ActionResult About()
    {
        ViewData["Title"] = "About Page";

        return View();
    }

     public ActionResult ClickMe()
    {
        TempData["Clicked"] = true;

        return RedirectToAction("Index");
    }

    [NonAction]
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Trace.Write("(Controller)Action Executing: " +
            filterContext.ActionDescriptor.ActionName);

        base.OnActionExecuting(filterContext);
    }

    [NonAction]
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Exception != null)
            filterContext.HttpContext.Trace.Write("(Controller)Exception thrown");

        base.OnActionExecuted(filterContext);
    }
}


Oltre a contrassegnare singoli metodi di azione con un filtro azioni, è possibile contrassegnare una classe controller nel suo complesso con un filtro azioni. In tal caso, il filtro si applica a tutti i metodi di azione di tale controller.

In aggiunta, se il controller deriva da un altro controller, il controller di base potrebbe disporre di attributi di filtro dell'azione personalizzati. In modo analogo, se il controller esegue l'override di un metodo di azione da un controller di base, il metodo potrebbe disporre di attributi di filtro dell'azione personalizzati, nonché di quelli ereditati dal metodo di azione di cui è stato eseguito l'override.

Per facilitare la comprensione dell'interazione tra filtri azione, i metodi di azione vengono raggruppati in ambiti. Un ambito definisce la modalità di applicazione dell'attributo, ad esempio se contrassegna una classe o un metodo e se contrassegna una classe di base o una classe derivata.

Ogni filtro azioni presenta una proprietà Order che viene utilizzata per determinare l'ordine in cui vengono eseguiti i filtri nell'ambito del filtro. La proprietà Order accetta un valore intero che deve essere 0 (valore predefinito) o superiore (con un'eccezione). L'omissione della proprietà Order assegna al filtro un valore di ordine pari a -1, che corrisponde a un ordine non specificato. Qualsiasi filtro azioni in un ambito la cui proprietà Order sia impostata su -1 verrà eseguito in un ordine non determinato, ma prima dei filtri che dispongono di un ordine specificato.

Quando viene specificata una proprietà Order di un filtro, questa deve essere impostata su un valore univoco all'interno di un ambito. Se due o più filtri azione all'interno di un ambito dispongono dello stesso valore per la proprietà Order, viene generata un'eccezione.

I filtri azione vengono eseguiti in un ordine che soddisfa i vincoli seguenti. Se più ordinamenti soddisfano tutti i vincoli, l'ordinamento non è determinato.

  1. L'implementazione dei metodi OnActionExecuting e OnActionExecuted nel controller viene sempre eseguita per prima. Per ulteriori informazioni, vedere Esecuzione di codice prima o dopo un'azione dall'interno di un controller.

  2. A meno che la proprietà Order non venga impostata in modo esplicito, un filtro di azione dispone di un ordine implicito corrispondente a -1.

  3. Se la proprietà Order di più filtri di azione viene impostata in modo esplicito, il filtro con il valore inferiore viene eseguito prima di quelli con valori superiori, come illustrato nell'esempio seguente:

    <Filter1(Order = 2)> _ 
    <Filter2(Order = 3)> _ 
    <Filter3(Order = 1)> _ 
    Public Sub Index()
        View("Index")
    End Sub
    

    [Filter1(Order = 2)]
    [Filter2(Order = 3)]
    [Filter3(Order = 1)]
    public void Index()
    {
        View("Index");
    }
    

    In questo esempio i filtri azione vengono eseguito nell'ordine seguente: Filter3, Filter1, quindi Filter2.

  4. Se due filtri azione dispongono dello stesso valore per la proprietà Order e se un filtro azioni viene definito in un tipo e l'altro filtro azioni viene definito in un metodo, viene eseguito per primo il filtro azioni definito nel tipo. Nell'esempio seguente vengono illustrati due filtri azioni, di cui uno definito nel tipo e un altro definito in un metodo.

    <FilterType(Order = 1)> _ 
    Public Class MyController
        <FilterMethod(Order = 1)> _ 
        Public  Sub Index()
            View("Index")
        End Sub
    End Class
    

    [FilterType(Order = 1)]
    public class MyController
    {
        [FilterMethod(Order = 1)]
        public void Index()
        {
            View("Index");
        }
    }
    

    In questo esempio FilterType viene eseguito prima di FilterMethod.

Aggiunte alla community

AGGIUNGI
Mostra:
© 2015 Microsoft