Metody filtrowania dla Razor stron w ASP.NET CoreFilter methods for Razor Pages in ASP.NET Core

Autor: Rick AndersonBy Rick Anderson

RazorIPageFilter i IAsyncPageFilter umożliwiają Razor stronom uruchamianie kodu przed Razor uruchomieniem programu obsługi stron i po nim.Razor Page filters IPageFilter and IAsyncPageFilter allow Razor Pages to run code before and after a Razor Page handler is run. Razor Filtry stron są podobne do ASP.NET Core filtrów akcji MVC, z wyjątkiem sytuacji, gdy nie można ich zastosować do metod obsługi poszczególnych stron.Razor Page filters are similar to ASP.NET Core MVC action filters, except they can't be applied to individual page handler methods.

Razor Filtry stron:Razor Page filters:

  • Uruchom kod po wybraniu metody obsługi, ale przed wystąpieniem powiązania modelu.Run code after a handler method has been selected, but before model binding occurs.
  • Uruchom kod przed wykonaniem metody obsługi, po utworzeniu powiązania modelu.Run code before the handler method executes, after model binding is complete.
  • Uruchom kod po wykonaniu metody obsługi.Run code after the handler method executes.
  • Można zaimplementować na stronie lub globalnie.Can be implemented on a page or globally.
  • Nie można zastosować do określonych metod obsługi stron.Cannot be applied to specific page handler methods.
  • Może mieć zależności konstruktora wypełniane przez iniekcję zależności (di).Can have constructor dependencies populated by Dependency Injection (DI). Aby uzyskać więcej informacji, zobacz Servicefilterattribute i TypeFilterAttribute.For more information, see ServiceFilterAttribute and TypeFilterAttribute.

Podczas gdy konstruktory stron i oprogramowanie pośredniczące umożliwiają wykonywanie kodu niestandardowego przed wykonaniem metody obsługi, tylko Razor filtry strony umożliwiają dostęp do HttpContext i strony.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. Oprogramowanie pośredniczące ma dostęp do programu HttpContext , ale nie do "kontekstu strony".Middleware has access to the HttpContext, but not to the "page context". Filtry mają FilterContext parametr pochodny, który zapewnia dostęp do HttpContext .Filters have a FilterContext derived parameter, which provides access to HttpContext. Oto przykład dla filtru strony: implementuje atrybut filtru , który dodaje nagłówek do odpowiedzi, co nie można wykonać za pomocą konstruktorów lub oprogramowania pośredniczącego.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. Dostęp do kontekstu strony, który obejmuje dostęp do wystąpień strony i jej modelu, jest dostępny tylko w przypadku wykonywania filtrów, programów obsługi lub treści Razor strony.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.

Wyświetl lub pobierz przykładowy kod (jak pobrać)View or download sample code (how to download)

Razor Filtry stron oferują następujące metody, które mogą być stosowane globalnie lub na poziomie strony:Razor Page filters provide the following methods, which can be applied globally or at the page level:

  • Metody synchroniczne:Synchronous methods:

  • Metody asynchroniczne:Asynchronous methods:

Implementowanie synchronicznej lub asynchronicznej wersji interfejsu filtru , a nie obu.Implement either the synchronous or the async version of a filter interface, not both. Struktura sprawdza najpierw, czy filtr implementuje interfejs asynchroniczny, a jeśli tak, wywołuje to.The framework checks first to see if the filter implements the async interface, and if so, it calls that. Jeśli nie, wywołuje metody interfejsu synchronicznego.If not, it calls the synchronous interface's method(s). W przypadku implementacji obu interfejsów są wywoływane tylko metody asynchroniczne.If both interfaces are implemented, only the async methods are called. Ta sama reguła dotyczy zastąpień na stronach, implementuje synchroniczną lub asynchroniczną wersję przesłonięcia, a nie obu.The same rule applies to overrides in pages, implement the synchronous or the async version of the override, not both.

Implementowanie Razor filtrów stron globalnieImplement Razor Page filters globally

Poniższy kod implementuje IAsyncPageFilter :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();
    }
}

W poprzednim kodzie ProcessUserAgent.Write jest podany przez użytkownika kod, który działa z ciągiem agenta użytkownika.In the preceding code, ProcessUserAgent.Write is user supplied code that works with the user agent string.

Poniższy kod włącza SampleAsyncPageFilter w Startup klasie: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));
        });
}

Poniższy kod wywołuje AddFolderApplicationModelConvention , aby zastosować SampleAsyncPageFilter tylko do stron w /Movies :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)));
    });
}

Poniższy kod implementuje synchroniczne IPageFilter :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.");
    }
}

Poniższy kod włącza SamplePageFilter :The following code enables the SamplePageFilter:

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

Implementowanie Razor filtrów stron przez zastępowanie metod filtrowaniaImplement Razor Page filters by overriding filter methods

Poniższy kod przesłania asynchroniczne Razor filtry stron: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();
    }
}

Implementowanie atrybutu filtruImplement a filter attribute

Wbudowany filtr filtru oparty na atrybutach OnResultExecutionAsync może być podklasą.The built-in attribute-based filter OnResultExecutionAsync filter can be subclassed. Poniższy filtr dodaje nagłówek do odpowiedzi: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 });
        }
    }
}

Poniższy kod stosuje AddHeader atrybut: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()
        {

        }
    }
}

Użyj narzędzia, takiego jak narzędzia deweloperskie przeglądarki, aby przeanalizować nagłówki.Use a tool such as the browser developer tools to examine the headers. W obszarze nagłówki odpowiedzi author: Rick jest wyświetlany.Under Response Headers , author: Rick is displayed.

Zobacz przesłanianie domyślnej kolejności, Aby uzyskać instrukcje dotyczące zastępowania kolejności.See Overriding the default order for instructions on overriding the order.

Zobacz Anulowanie i krótkie obwody , aby uzyskać instrukcje dotyczące krótkiego obwodu potoku filtru z filtru.See Cancellation and short circuiting for instructions to short-circuit the filter pipeline from a filter.

Autoryzuj atrybut filtruAuthorize filter attribute

Atrybut Autoryzuj można zastosować do PageModel :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();
    }
}

Autor: Rick AndersonBy Rick Anderson

RazorIPageFilter i IAsyncPageFilter umożliwiają Razor stronom uruchamianie kodu przed Razor uruchomieniem programu obsługi stron i po nim.Razor Page filters IPageFilter and IAsyncPageFilter allow Razor Pages to run code before and after a Razor Page handler is run. Razor Filtry stron są podobne do ASP.NET Core filtrów akcji MVC, z wyjątkiem sytuacji, gdy nie można ich zastosować do metod obsługi poszczególnych stron.Razor Page filters are similar to ASP.NET Core MVC action filters, except they can't be applied to individual page handler methods.

Razor Filtry stron:Razor Page filters:

  • Uruchom kod po wybraniu metody obsługi, ale przed wystąpieniem powiązania modelu.Run code after a handler method has been selected, but before model binding occurs.
  • Uruchom kod przed wykonaniem metody obsługi, po utworzeniu powiązania modelu.Run code before the handler method executes, after model binding is complete.
  • Uruchom kod po wykonaniu metody obsługi.Run code after the handler method executes.
  • Można zaimplementować na stronie lub globalnie.Can be implemented on a page or globally.
  • Nie można zastosować do określonych metod obsługi stron.Cannot be applied to specific page handler methods.

Kod można uruchomić przed wykonaniem metody obsługi przy użyciu konstruktora stron lub oprogramowania pośredniczącego, ale tylko Razor filtry strony mają dostęp do elementu 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. Filtry mają parametr pochodny FilterContext , który zapewnia dostęp do HttpContext .Filters have a FilterContext derived parameter, which provides access to HttpContext. Na przykład, implementacja przykładu atrybutu filtru dodaje nagłówek do odpowiedzi, co nie jest możliwe za pomocą konstruktorów lub oprogramowania pośredniczącego.For example, the Implement a filter attribute sample adds a header to the response, something that can't be done with constructors or middleware.

Wyświetl lub pobierz przykładowy kod (jak pobrać)View or download sample code (how to download)

Razor Filtry stron oferują następujące metody, które mogą być stosowane globalnie lub na poziomie strony:Razor Page filters provide the following methods, which can be applied globally or at the page level:

  • Metody synchroniczne:Synchronous methods:

  • Metody asynchroniczne:Asynchronous methods:

Uwaga

Implementowanie synchronicznej lub asynchronicznej wersji interfejsu filtru , a nie obu.Implement either the synchronous or the async version of a filter interface, not both. Struktura sprawdza najpierw, czy filtr implementuje interfejs asynchroniczny, a jeśli tak, wywołuje to.The framework checks first to see if the filter implements the async interface, and if so, it calls that. Jeśli nie, wywołuje metody interfejsu synchronicznego.If not, it calls the synchronous interface's method(s). W przypadku implementacji obu interfejsów są wywoływane tylko metody asynchroniczne.If both interfaces are implemented, only the async methods are called. Ta sama reguła dotyczy zastąpień na stronach, implementuje synchroniczną lub asynchroniczną wersję przesłonięcia, a nie obu.The same rule applies to overrides in pages, implement the synchronous or the async version of the override, not both.

Implementowanie Razor filtrów stron globalnieImplement Razor Page filters globally

Poniższy kod implementuje IAsyncPageFilter :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();
        }
    }
}

W poprzednim kodzie ILogger nie jest wymagana.In the preceding code, ILogger is not required. Jest on używany w przykładzie w celu zapewnienia informacji o śledzeniu dla aplikacji.It's used in the sample to provide trace information for the application.

Poniższy kod włącza SampleAsyncPageFilter w Startup klasie:The following code enables the SampleAsyncPageFilter in the Startup class:

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

Poniższy kod przedstawia kompletną Startup klasę: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();
        }
    }
}

Poniższy kod wywołuje AddFolderApplicationModelConvention , aby zastosować SampleAsyncPageFilter tylko do stron w /subFolder :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)));
       });
}

Poniższy kod implementuje synchroniczne IPageFilter :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.");
        }
    }
}

Poniższy kod włącza SamplePageFilter :The following code enables the SamplePageFilter:

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

Implementowanie Razor filtrów stron przez zastępowanie metod filtrowaniaImplement Razor Page filters by overriding filter methods

Poniższy kod przesłania synchroniczne Razor filtry stron: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");
        }
    }
}

Implementowanie atrybutu filtruImplement a filter attribute

Wbudowany filtr OnResultExecutionAsync filtru oparty na atrybutach może być podklasą.The built-in attribute-based filter OnResultExecutionAsync filter can be subclassed. Poniższy filtr dodaje nagłówek do odpowiedzi: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 });
        }
    }
}

Poniższy kod stosuje AddHeader atrybut: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;
    }
}

Zobacz przesłanianie domyślnej kolejności, Aby uzyskać instrukcje dotyczące zastępowania kolejności.See Overriding the default order for instructions on overriding the order.

Zobacz Anulowanie i krótkie obwody , aby uzyskać instrukcje dotyczące krótkiego obwodu potoku filtru z filtru.See Cancellation and short circuiting for instructions to short-circuit the filter pipeline from a filter.

Autoryzuj atrybut filtruAuthorize filter attribute

Atrybut Autoryzuj można zastosować do PageModel :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();
    }
}