Filtermethoden für Razor-Seiten in ASP-NET CoreFilter methods for Razor Pages in ASP.NET Core

Von Rick AndersonBy Rick Anderson

Eine Razor-Seite filtert IPageFilter. IAsyncPageFilter erlaubt Razor-Seiten Code auszuführen, bevor und nachdem ein Handler für Razor-Seiten ausgeführt wurde.Razor Page filters IPageFilter and IAsyncPageFilter allow Razor Pages to run code before and after a Razor Page handler is run. Filter für Razor-Seiten ähneln ASP.NET Core MVC-Aktionsfiltern, können allerdings nicht auf einzelne Seitenhandlermethoden angewendet werden.Razor Page filters are similar to ASP.NET Core MVC action filters, except they can't be applied to individual page handler methods.

Filter für Razor Pages:Razor Page filters:

  • Führen Code aus, nachdem eine Handlermethode ausgewählt wurde, aber bevor die Modellbindung erfolgtRun code after a handler method has been selected, but before model binding occurs.
  • Führen Code aus, bevor die Handlermethode ausgeführt wird, nachdem die Modellbindung abgeschlossen istRun code before the handler method executes, after model binding is complete.
  • Führen Code aus, nachdem die Handlermethode ausgeführt wirdRun code after the handler method executes.
  • Können auf einer Seite oder global implementiert werdenCan be implemented on a page or globally.
  • Können nicht auf seitenspezifische Handlermethoden angewendet werdenCannot be applied to specific page handler methods.
  • Alle Konstruktorabhängigkeiten werden durch die Abhängigkeitsinjektion aufgefüllt.Can have constructor dependencies populated by Dependency Injection (DI). Weitere Informationen finden Sie unter ServiceFilterAttribute und TypeFilterAttribute.For more information, see ServiceFilterAttribute and TypeFilterAttribute.

Während Seitenkonstruktoren und Middleware die Ausführung von benutzerdefiniertem Code vor der Ausführung einer Handlermethode ermöglichen, gestatten nur Razor Page-Filter den Zugriff auf HttpContext und die Seite.While page constructors and middleware enable executing custom code before a handler method executes, only Razor Page filters enable access to HttpContext and the page. Middleware hat Zugriff auf den HttpContext, aber nicht auf den „Seitenkontext“.Middleware has access to the HttpContext, but not to the "page context". Filter verfügen über einen Parameter, der von FilterContext abgeleitet ist, um Zugriff auf HttpContext zu ermöglichen.Filters have a FilterContext derived parameter, which provides access to HttpContext. Im Folgenden finden Sie ein Beispiel für einen Seitenfilter: Implementieren eines Filterattributs fügt der Antwort einen Header hinzu. Dies kann nicht über Konstruktoren oder Middleware erfolgen.Here's a sample for a page filter: Implement a filter attribute that adds a header to the response, something that can't be done with constructors or middleware. Der Zugriff auf den Seitenkontext, der den Zugriff auf die Instanzen der Seite und ihr Modell enthält, ist nur verfügbar, wenn Filter, Handler oder der Text einer Razor-Seite ausgeführt werden.Access to the page context, which includes access to the instances of the page and it's model, are only available when executing filters, handlers, or the body of a Razor Page.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)View or download sample code (how to download)

Filter für Razor-Seiten bieten die folgenden Methoden, die global oder auf Seitenebene angewendet werden können:Razor Page filters provide the following methods, which can be applied globally or at the page level:

  • Synchrone Methoden:Synchronous methods:

    • OnPageHandlerSelected: Wird aufgerufen, nachdem eine Handlermethode ausgewählt wurde, aber bevor die Modellbindung erfolgt.OnPageHandlerSelected : Called after a handler method has been selected, but before model binding occurs.
    • OnPageHandlerExecuting: Wird aufgerufen, bevor die Handlermethode ausgeführt wird, nachdem die Modellbindung abgeschlossen ist.OnPageHandlerExecuting : Called before the handler method executes, after model binding is complete.
    • OnPageHandlerExecuted: Wird aufgerufen, nachdem die Handlermethode ausgeführt wird, bevor das Aktionsergebnis angezeigt wird.OnPageHandlerExecuted : Called after the handler method executes, before the action result.
  • Asynchrone Methoden:Asynchronous methods:

Implementieren Sie entweder die synchrone oder asynchrone Version einer Filterschnittstelle, aber nicht beide.Implement either the synchronous or the async version of a filter interface, not both. Das Framework prüft zuerst, ob der Filter die asynchrone Schnittstelle implementiert, und wenn dies der Fall ist, ruft es sie auf.The framework checks first to see if the filter implements the async interface, and if so, it calls that. Wenn dies nicht der Fall ist, ruft es die Methode(n) der synchronen Schnittstelle auf.If not, it calls the synchronous interface's method(s). Wenn beide Schnittstellen implementiert werden, werden nur die asynchronen Methoden aufgerufen.If both interfaces are implemented, only the async methods are called. Die gleiche Regel gilt für Überschreibungen in Seiten. Implementieren Sie die synchrone oder asynchrone Version der Überschreibung, nicht beide.The same rule applies to overrides in pages, implement the synchronous or the async version of the override, not both.

Globales implementieren von Filtern für Razor-SeitenImplement Razor Page filters globally

Mit dem folgenden Code wird das IAsyncPageFilter-Element implementiert:The following code implements IAsyncPageFilter:

public class SampleAsyncPageFilter : IAsyncPageFilter
{
    private readonly IConfiguration _config;

    public SampleAsyncPageFilter(IConfiguration config)
    {
        _config = config;
    }

    public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
    {
        var key = _config["UserAgentID"];
        context.HttpContext.Request.Headers.TryGetValue("user-agent",
                                                        out StringValues value);
        ProcessUserAgent.Write(context.ActionDescriptor.DisplayName,
                               "SampleAsyncPageFilter.OnPageHandlerSelectionAsync",
                               value, key.ToString());

        return Task.CompletedTask;
    }

    public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context,
                                                  PageHandlerExecutionDelegate next)
    {
        // Do post work.
        await next.Invoke();
    }
}

Im vorhergehenden Code ist ProcessUserAgent.Write der vom Benutzer bereitgestellte Code, der mit der Benutzer-Agent-Zeichenfolge arbeitet.In the preceding code, ProcessUserAgent.Write is user supplied code that works with the user agent string.

Der folgende Code aktiviert SampleAsyncPageFilter in der Startup-Klasse:The following code enables the SampleAsyncPageFilter in the Startup class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.Filters.Add(new SampleAsyncPageFilter(Configuration));
        });
}

Der folgende Code ruft AddFolderApplicationModelConvention auf, damit SampleAsyncPageFilter nur auf Seiten in /Movies angewendet wird:The following code calls AddFolderApplicationModelConvention to apply the SampleAsyncPageFilter to only pages in /Movies:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages(options =>
    {
        options.Conventions.AddFolderApplicationModelConvention(
            "/Movies",
            model => model.Filters.Add(new SampleAsyncPageFilter(Configuration)));
    });
}

Im folgenden Code wird IPageFilter synchron implementiert:The following code implements the synchronous IPageFilter:

public class SamplePageFilter : IPageFilter
{
    private readonly IConfiguration _config;

    public SamplePageFilter(IConfiguration config)
    {
        _config = config;
    }

    public void OnPageHandlerSelected(PageHandlerSelectedContext context)
    {
        var key = _config["UserAgentID"];
        context.HttpContext.Request.Headers.TryGetValue("user-agent", out StringValues value);
        ProcessUserAgent.Write(context.ActionDescriptor.DisplayName,
                               "SamplePageFilter.OnPageHandlerSelected",
                               value, key.ToString());
    }

    public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
    {
        Debug.WriteLine("Global sync OnPageHandlerExecuting called.");
    }

    public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
    {
        Debug.WriteLine("Global sync OnPageHandlerExecuted called.");
    }
}

Der folgende Code aktiviert SamplePageFilter:The following code enables the SamplePageFilter:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages()
        .AddMvcOptions(options =>
        {
            options.Filters.Add(new SamplePageFilter(Configuration));
        });
}

Implementieren von Filtern für Razor-Seiten durch Überschreiben von FiltermethodenImplement Razor Page filters by overriding filter methods

Der folgende Code überschreibt die asynchronen Razor Page-Filter:The following code overrides the asynchronous Razor Page filters:

public class IndexModel : PageModel
{
    private readonly IConfiguration _config;

    public IndexModel(IConfiguration config)
    {
        _config = config;
    }

    public override Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
    {
        Debug.WriteLine("/IndexModel OnPageHandlerSelectionAsync");
        return Task.CompletedTask;
    }

    public async override Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, 
                                                           PageHandlerExecutionDelegate next)
    {
        var key = _config["UserAgentID"];
        context.HttpContext.Request.Headers.TryGetValue("user-agent", out StringValues value);
        ProcessUserAgent.Write(context.ActionDescriptor.DisplayName,
                               "/IndexModel-OnPageHandlerExecutionAsync",
                                value, key.ToString());

        await next.Invoke();
    }
}

Implementieren eines FilterattributsImplement a filter attribute

Der integrierte attributbasierte Filter OnResultExecutionAsync kann als Unterklasse definiert werden.The built-in attribute-based filter OnResultExecutionAsync filter can be subclassed. Der folgende Filter fügt der Antwort einen Header hinzu:The following filter adds a header to the response:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;

namespace PageFilter.Filters
{
    public class AddHeaderAttribute  : ResultFilterAttribute
    {
        private readonly string _name;
        private readonly string _value;

        public AddHeaderAttribute (string name, string value)
        {
            _name = name;
            _value = value;
        }

        public override void OnResultExecuting(ResultExecutingContext context)
        {
            context.HttpContext.Response.Headers.Add(_name, new string[] { _value });
        }
    }
}

Der folgende Code wendet das Attribut AddHeader an:The following code applies the AddHeader attribute:

using Microsoft.AspNetCore.Mvc.RazorPages;
using PageFilter.Filters;

namespace PageFilter.Movies
{
    [AddHeader("Author", "Rick")]
    public class TestModel : PageModel
    {
        public void OnGet()
        {

        }
    }
}

Verwenden Sie ein Tool wie die Browser-Entwicklertools, um die Header zu untersuchen.Use a tool such as the browser developer tools to examine the headers. Unter Antwortheader wird author: Rick angezeigt.Under Response Headers, author: Rick is displayed.

Informationen zum Überschreiben der Reihenfolge finden Sie unter Überschreiben der Standardreihenfolge.See Overriding the default order for instructions on overriding the order.

Informationen zum Kurzschließen der Filterpipeline eines Filters finden Sie unter Abbrechen und Kurzschließen.See Cancellation and short circuiting for instructions to short-circuit the filter pipeline from a filter.

Autorisieren eines FilterattributsAuthorize filter attribute

Das Attribut Authorize kann auf ein PageModel angewendet werden:The Authorize attribute can be applied to a PageModel:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace PageFilter.Pages
{
    [Authorize]
    public class ModelWithAuthFilterModel : PageModel
    {
        public IActionResult OnGet() => Page();
    }
}

Von Rick AndersonBy Rick Anderson

Eine Razor-Seite filtert IPageFilter. IAsyncPageFilter erlaubt Razor-Seiten Code auszuführen, bevor und nachdem ein Handler für Razor-Seiten ausgeführt wurde.Razor Page filters IPageFilter and IAsyncPageFilter allow Razor Pages to run code before and after a Razor Page handler is run. Filter für Razor-Seiten ähneln ASP.NET Core MVC-Aktionsfiltern, können allerdings nicht auf einzelne Seitenhandlermethoden angewendet werden.Razor Page filters are similar to ASP.NET Core MVC action filters, except they can't be applied to individual page handler methods.

Filter für Razor Pages:Razor Page filters:

  • Führen Code aus, nachdem eine Handlermethode ausgewählt wurde, aber bevor die Modellbindung erfolgtRun code after a handler method has been selected, but before model binding occurs.
  • Führen Code aus, bevor die Handlermethode ausgeführt wird, nachdem die Modellbindung abgeschlossen istRun code before the handler method executes, after model binding is complete.
  • Führen Code aus, nachdem die Handlermethode ausgeführt wirdRun code after the handler method executes.
  • Können auf einer Seite oder global implementiert werdenCan be implemented on a page or globally.
  • Können nicht auf seitenspezifische Handlermethoden angewendet werdenCannot be applied to specific page handler methods.

Code kann ausgeführt werden, bevor eine Handlermethode ausgeführt wird, indem man den Seitenkonstruktor oder Middleware benutzt, aber nur Filter für Razor-Seiten haben Zugriff auf HttpContext.Code can be run before a handler method executes using the page constructor or middleware, but only Razor Page filters have access to HttpContext. Filter verfügen über einen Parameter, der von FilterContext abgeleitet ist, um Zugriff auf HttpContext zu ermöglichen.Filters have a FilterContext derived parameter, which provides access to HttpContext. Das Beispiel Implementieren eines Filterattributs fügt der Antwort z.B. einen Header hinzu. Dies kann nicht über Konstruktoren oder Middleware erfolgen.For example, the Implement a filter attribute sample adds a header to the response, something that can't be done with constructors or middleware.

Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)View or download sample code (how to download)

Filter für Razor-Seiten bieten die folgenden Methoden, die global oder auf Seitenebene angewendet werden können:Razor Page filters provide the following methods, which can be applied globally or at the page level:

  • Synchrone Methoden:Synchronous methods:

    • OnPageHandlerSelected: Wird aufgerufen, nachdem eine Handlermethode ausgewählt wurde, aber bevor die Modellbindung erfolgt.OnPageHandlerSelected : Called after a handler method has been selected, but before model binding occurs.
    • OnPageHandlerExecuting: Wird aufgerufen, bevor die Handlermethode ausgeführt wird, nachdem die Modellbindung abgeschlossen ist.OnPageHandlerExecuting : Called before the handler method executes, after model binding is complete.
    • OnPageHandlerExecuted: Wird aufgerufen, nachdem die Handlermethode ausgeführt wird, bevor das Aktionsergebnis angezeigt wird.OnPageHandlerExecuted : Called after the handler method executes, before the action result.
  • Asynchrone Methoden:Asynchronous methods:

Hinweis

Implementieren Sie entweder die synchrone oder asynchrone Version einer Filterschnittstelle, aber nicht beide.Implement either the synchronous or the async version of a filter interface, not both. Das Framework prüft zuerst, ob der Filter die asynchrone Schnittstelle implementiert, und wenn dies der Fall ist, ruft es sie auf.The framework checks first to see if the filter implements the async interface, and if so, it calls that. Wenn dies nicht der Fall ist, ruft es die Methode(n) der synchronen Schnittstelle auf.If not, it calls the synchronous interface's method(s). Wenn beide Schnittstellen implementiert werden, werden nur die asynchronen Methoden aufgerufen.If both interfaces are implemented, only the async methods are called. Die gleiche Regel gilt für Überschreibungen in Seiten. Implementieren Sie die synchrone oder asynchrone Version der Überschreibung, nicht beide.The same rule applies to overrides in pages, implement the synchronous or the async version of the override, not both.

Globales implementieren von Filtern für Razor-SeitenImplement Razor Page filters globally

Mit dem folgenden Code wird das IAsyncPageFilter-Element implementiert:The following code implements IAsyncPageFilter:

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace PageFilter.Filters
{
    public class SampleAsyncPageFilter : IAsyncPageFilter
    {
        private readonly ILogger _logger;

        public SampleAsyncPageFilter(ILogger logger)
        {
            _logger = logger;
        }

        public async Task OnPageHandlerSelectionAsync(
                                            PageHandlerSelectedContext context)
        {
            _logger.LogDebug("Global OnPageHandlerSelectionAsync called.");
            await Task.CompletedTask;
        }

        public async Task OnPageHandlerExecutionAsync(
                                            PageHandlerExecutingContext context,
                                            PageHandlerExecutionDelegate next)
        {
            _logger.LogDebug("Global OnPageHandlerExecutionAsync called.");
            await next.Invoke();
        }
    }
}

Im vorhergehenden Code wird ILogger nicht benötigt.In the preceding code, ILogger is not required. Es wird im Beispiel verwendet, um Überwachungsinformationen für die Anwendung bereitzustellen.It's used in the sample to provide trace information for the application.

Der folgende Code aktiviert SampleAsyncPageFilter in der Startup-Klasse:The following code enables the SampleAsyncPageFilter in the Startup class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(new SampleAsyncPageFilter(_logger));
    });
}

Der folgende Code veranschaulicht die vollständige Startup-Klasse:The following code shows the complete Startup class:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PageFilter.Filters;

namespace PageFilter
{
    public class Startup
    {
        ILogger _logger;
        public Startup(ILoggerFactory loggerFactory, IConfiguration configuration)
        {
            _logger = loggerFactory.CreateLogger<GlobalFiltersLogger>();
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options =>
            {
                options.Filters.Add(new SampleAsyncPageFilter(_logger));
            });
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseMvc();
        }
    }
}

Der folgende Code ruft AddFolderApplicationModelConvention auf, damit SampleAsyncPageFilter nur auf Seiten in /subFolder angewendet wird:The following code calls AddFolderApplicationModelConvention to apply the SampleAsyncPageFilter to only pages in /subFolder:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
       .AddRazorPagesOptions(options =>
       {
           options.Conventions.AddFolderApplicationModelConvention(
               "/subFolder",
               model => model.Filters.Add(new SampleAsyncPageFilter(_logger)));
       });
}

Im folgenden Code wird IPageFilter synchron implementiert:The following code implements the synchronous IPageFilter:

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;

namespace PageFilter.Filters
{
    public class SamplePageFilter : IPageFilter
    {
        private readonly ILogger _logger;

        public SamplePageFilter(ILogger logger)
        {
            _logger = logger;
        }

        public void OnPageHandlerSelected(PageHandlerSelectedContext context)
        {
            _logger.LogDebug("Global sync OnPageHandlerSelected called.");
        }

        public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
        {
            _logger.LogDebug("Global sync PageHandlerExecutingContext called.");
        }

        public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
        {
            _logger.LogDebug("Global sync OnPageHandlerExecuted called.");
        }
    }
}

Der folgende Code aktiviert SamplePageFilter:The following code enables the SamplePageFilter:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(new SamplePageFilter(_logger));
    });
}

Implementieren von Filtern für Razor-Seiten durch Überschreiben von FiltermethodenImplement Razor Page filters by overriding filter methods

Der folgende Code überschreibt die synchronen Razor Page-Filter:The following code overrides the synchronous Razor Page filters:

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace PageFilter.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger _logger;

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }
        public string Message { get; set; }

        public void OnGet()
        {
            _logger.LogDebug("IndexModel/OnGet");
        }
        
        public override void OnPageHandlerSelected(
                                    PageHandlerSelectedContext context)
        {
            _logger.LogDebug("IndexModel/OnPageHandlerSelected");          
        }

        public override void OnPageHandlerExecuting(
                                    PageHandlerExecutingContext context)
        {
            Message = "Message set in handler executing";
            _logger.LogDebug("IndexModel/OnPageHandlerExecuting");
        }


        public override void OnPageHandlerExecuted(
                                    PageHandlerExecutedContext context)
        {
            _logger.LogDebug("IndexModel/OnPageHandlerExecuted");
        }
    }
}

Implementieren eines FilterattributsImplement a filter attribute

Der integrierte attributbasierte Filter OnResultExecutionAsync kann als Unterklasse definiert werden.The built-in attribute-based filter OnResultExecutionAsync filter can be subclassed. Der folgende Filter fügt der Antwort einen Header hinzu:The following filter adds a header to the response:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;

namespace PageFilter.Filters
{
    public class AddHeaderAttribute  : ResultFilterAttribute
    {
        private readonly string _name;
        private readonly string _value;

        public AddHeaderAttribute (string name, string value)
        {
            _name = name;
            _value = value;
        }

        public override void OnResultExecuting(ResultExecutingContext context)
        {
            context.HttpContext.Response.Headers.Add(_name, new string[] { _value });
        }
    }
}

Der folgende Code wendet das Attribut AddHeader an:The following code applies the AddHeader attribute:

[AddHeader("Author", "Rick")]
public class ContactModel : PageModel
{
    private readonly ILogger _logger;

    public ContactModel(ILogger<ContactModel> logger)
    {
        _logger = logger;
    }
    public string Message { get; set; }

    public async Task OnGetAsync()
    {
        Message = "Your contact page.";
        _logger.LogDebug("Contact/OnGet");
        await Task.CompletedTask;
    }
}

Informationen zum Überschreiben der Reihenfolge finden Sie unter Überschreiben der Standardreihenfolge.See Overriding the default order for instructions on overriding the order.

Informationen zum Kurzschließen der Filterpipeline eines Filters finden Sie unter Abbrechen und Kurzschließen.See Cancellation and short circuiting for instructions to short-circuit the filter pipeline from a filter.

Autorisieren eines FilterattributsAuthorize filter attribute

Das Attribut Authorize kann auf ein PageModel angewendet werden:The Authorize attribute can be applied to a PageModel:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace PageFilter.Pages
{
    [Authorize]
    public class ModelWithAuthFilterModel : PageModel
    {
        public IActionResult OnGet() => Page();
    }
}