(0) exportieren Drucken
Alle erweitern
Dieser Artikel wurde manuell übersetzt. Bewegen Sie den Mauszeiger über die Sätze im Artikel, um den Originaltext anzuzeigen.
Übersetzung
Original

Erstellen von benutzerdefinierten Aktionsfiltern

.NET Framework 4

Die möglichen Verwendungen für Aktionsfilter sind so vielfältig wie die Aktionen, auf die sie angewendet werden können. Einige mögliche Verwendungen für Aktionsfilter sind:

  • Protokollieren von Benutzerinteraktionen.

  • "Anti-Bild-leeching", um zu verhindern, dass Bilder in Seiten geladen werden, die nicht von der Website stammen.

  • Filtern von Webcrawlern, um das Anwendungsverhalten ausgehend vom Browser-Benutzer-Agent zu ändern.

  • Lokalisierung zum Festlegen des Gebietsschemas.

  • Dynamische Aktionen, um eine Aktion in einen Controller einzufügen.

Ein Aktionsfilter wird als Attributklasse implementiert, die von ActionFilterAttribute erbt. ActionFilterAttribute ist eine abstrakte Klasse, die über vier virtuelle Methoden verfügt, die Sie überschreiben können: OnActionExecuting, OnActionExecuted, OnResultExecuting und OnResultExecuted. Um einen Aktionsfilter zu implementieren, müssen Sie mindestens eine dieser Methoden überschreiben.

Das ASP.NET-MVC-Framework ruft die OnActionExecuting-Methode des Aktionsfilters vor allen Aktionsmethoden auf, die mit dem Aktionsfilterattribut gekennzeichnet sind. Analog hierzu ruft das Framework die OnActionExecuted-Methode auf, nachdem die Aktionsmethode beendet wurde.

Die OnResultExecuting-Methode wird direkt vor der ActionResult-Instanz aufgerufen, die von der Aktion zurückgegeben wird. Die OnResultExecuted-Methode wird direkt nach dem Ausführen des Ergebnisses aufgerufen. Diese Methoden eignen sich für das Ausführen von Aktionen wie Protokollierung, Ausgabecaching usw.

Das folgende Beispiel zeigt einen einfachen Aktionsfilter, der Verfolgungsmeldungen vor und nach dem Aufrufen einer Aktionsmethode protokolliert.


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);
    }
}


Jede der Controllerereignishandler für die Aktionsfilterung erwartet ein Kontextobjekt als Parameter. In der folgenden Liste werden die Filterereignishandler und der erwartete Kontexttyp aufgeführt.

Alle Kontextklassen erben von der ControllerContext-Klasse und beinhalten eine ActionDescriptor-Eigenschaft. Anhand der ActionDescriptor-Eigenschaft können Sie ermitteln, welcher Aktion der Filter aktuell zugeordnet ist.

Die ActionExecutingContext-Klasse und ResultExecutingContext-Klasse enthalten eine Cancel-Eigenschaft, mit der die Aktion abgebrochen werden kann.

Die ActionExecutedContent-Klasse und die ResultExecutedContext-Klasse enthalten eine Exception-Eigenschaft und eine ExceptionHandled-Eigenschaft. Wenn die Exception-Eigenschaft den Wert null hat, zeigt dies an, dass beim Ausführen der Aktionsmethode kein Fehler aufgetreten ist. Wenn die Exception-Eigenschaft einen anderen Wert als null hat und der Filter die Ausnahme behandeln kann, kann die durchgeführte Behandlung signalisiert werden, indem die ExceptionHandled-Eigenschaft auf true festgelegt wird. Auch wenn die ExceptionHandled-Eigenschaft den Wert true hat, wird die OnActionExecuted-Methode oder die OnResultExecuted-Methode aller weiteren Aktionsfilter im Stapel aufgerufen, und es werden Informationen über die Ausnahme an die Methoden übergeben. Hierdurch kann z. B. ein Protokollierungsfilter eine Ausnahme protokollieren, obwohl die Ausnahme bereits behandelt wurde. Im Allgemeinen sollte ein Aktionsfilter keine Ausnahmen behandeln, außer wenn sich der Fehler direkt auf den Filter bezieht.

Sie können einen Aktionsfilter auf beliebig viele Aktionsmethoden anwenden. Das folgende Beispiel zeigt einen Controller mit Aktionsmethoden, die mit einem Aktionsfilterattribut gekennzeichnet sind. In diesem Fall rufen alle Aktionsmethoden im Controller denselben Aktionsfilter auf.


[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");
    }
}


Die Controller-Klasse von ASP.NET-MVC definiert die OnActionExecuting-Methode und die OnActionExecuted-Methode, die Sie überschreiben können. Wenn Sie eine oder beide dieser Methoden überschreiben, wird die Logik vor bzw. nach allen Aktionsmethoden des Controllers ausgeführt. Diese Funktionalität entspricht der von Aktionsfiltern, die Methoden werden jedoch im Bereich des Controllers ausgeführt.

Das folgende Beispiel zeigt die OnActionExecuting-Methode und die OnActionExecuted-Methode auf Controllerebene, die für alle Aktionsmethoden im Controller gelten.


[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);
    }
}


Zusätzlich zum Kennzeichnen einzelner Aktionsmethoden mit einem Aktionsfilter können Sie eine gesamte Controllerklasse mit einem Aktionsfilter kennzeichnen. In diesem Fall gilt der Filter für alle Aktionsmethoden dieses Controllers.

Wenn der Controller darüber hinaus von einem anderen Controller abgeleitet ist, kann der Basiscontroller ebenfalls über eigene Aktionsfilterattribute verfügen. Wenn Ihr Controller eine Aktionsmethode aus einem Basiscontroller überschreibt, kann die Methode sowohl über eigene Aktionsfilterattribute als auch über geerbte Attribute von der überschriebenen Aktionsmethode verfügen.

Um das Zusammenwirken von Aktionsfiltern besser verstehen zu können, werden Aktionsmethoden in Bereiche gegliedert. Ein Bereich definiert, wo das Attribut gültig ist, ob es z. B. eine Klasse oder eine Methode kennzeichnet und ob es eine Basisklasse oder eine abgeleitete Klasse kennzeichnet.

Jeder Aktionsfilter verfügt über eine Order-Eigenschaft, über die die Reihenfolge festgelegt wird, in der Filter im Bereich des Filters ausgeführt werden. Die Order-Eigenschaft erwartet einen ganzzahligen Wert, der 0 (Standard) oder größer sein muss (mit einer Ausnahme). Wenn die Order-Eigenschaft weggelassen wird, erhält der Filter den Reihenfolgenwert -1, der keine spezifische Reihenfolge angibt. Jeder Aktionsfilter in einem Bereich, dessen Order-Eigenschaft auf -1 festgelegt ist, wird in unbestimmter Reihenfolge, aber vor den Filtern mit angegebener Reihenfolge ausgeführt.

Wenn eine Order-Eigenschaft eines Filters angegeben wird, muss der Wert im Bereich eindeutig sein. Wenn zwei oder mehr Aktionsfilter in einem Bereich denselben Order-Eigenschaftswert haben, wird eine Ausnahme ausgelöst.

Aktionsfilter werden in einer Reihenfolge ausgeführt, die den folgenden Einschränkungen unterliegt. Wenn mehr als eine Reihenfolge alle diese Einschränkungen erfüllt, ist die Reihenfolge unbestimmt.

  1. Die Implementierung der OnActionExecuting-Methode und der OnActionExecuted-Methode des Controllers haben immer Priorität. Weitere Informationen finden Sie unter Ausführen von Code vor und nach einer Aktion innerhalb eines Controllers.

  2. Sofern die Order-Eigenschaft nicht explizit festgelegt wurde, hat ein Aktionsfilter eine implizite Reihenfolge von -1.

  3. Wenn die Order-Eigenschaft mehrerer Aktionsfilter explizit gesetzt ist, wird der Filter mit dem niedrigsten Wert vor denen mit größeren Werten ausgeführt, wie im folgenden Beispiel gezeigt:

    <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 diesem Beispiel würden die Aktionsfilter in der folgenden Reihenfolge ausgeführt werden: Filter3, Filter1 und dann Filter2.

  4. Wenn zwei Aktionsfilter über denselben Order-Eigenschaftswert verfügen und wenn ein Aktionsfilter für einen Typ und der andere Aktionsfilter für eine Methode definiert ist, wird der für den Typ definierte Aktionsfilter zuerst ausgeführt. Das folgende Beispiel zeigt zwei Aktionsfilter, von denen einer für den Typ und der andere für eine Methode definiert ist.

    <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 diesem Beispiel wird FilterType vor FilterMethod ausgeführt.

Community-Beiträge

HINZUFÜGEN
Anzeigen:
© 2014 Microsoft