ASP.NET Core filtreler

Kirk Larkabağı, Rick Anderson, Tom Dykstrave Steve Smith tarafından

ASP.NET Core filtreler , istek işleme ardışık düzeninde belirli aşamalardan önce veya sonra kod çalıştırılmasına izin verir.

Yerleşik Filtreler şunları gibi görevleri işler:

  • Yetkilendirme, bir kullanıcının yetkili olmadığı kaynaklara erişimi önler.
  • Yanıt önbelleğe alma, istek ardışık düzenini önbelleğe alınmış bir yanıt döndürecek şekilde işleme.

Çapraz kesme sorunlarını işlemek için özel filtreler oluşturulabilir. Çapraz kesme sorunlarına örnek olarak hata işleme, önbelleğe alma, yapılandırma, yetkilendirme ve günlüğe kaydetme dahildir. Filtreler kodu çoğaltmaktan kaçının. Örneğin, bir hata işleme özel durum filtresi hata işlemeyi birleştirebilir.

Bu belge Razor , görünümler içeren sayfalar, API denetleyicileri ve denetleyiciler için geçerlidir. Filtreler doğrudan Razor bileşenlerleçalışmaz. Filtre, şu durumlarda bir bileşeni yalnızca dolaylı olarak etkileyebilir:

  • Bileşen bir sayfa veya görünüme katıştırılır.
  • Sayfa veya denetleyici ve görünüm filtreyi kullanır.

Örneği (indirme) görüntüleyin veya indirin .

Filtreler nasıl çalışır?

filtreler, bazen filtre işlem hattı olarak da adlandırılan ASP.NET Core eylemi çağırma işlem hattı içinde çalışır. filtre işlem hattı çalıştırılacak eylemi ASP.NET Core seçtikten sonra çalışır.

İstek diğer ara yazılım, yönlendirme ara yazılımı, eylem seçimi ve eylem çağırma Işlem hattı aracılığıyla işlenir. İstek işleme, istemciye gönderilen bir yanıt olmadan önce eylem seçimi, yönlendirme ara yazılımı ve diğer diğer ara yazılım aracılığıyla yeniden devam eder.

Filtre türleri

Her filtre türü, filtre ardışık düzeninde farklı bir aşamada yürütülür:

  • İlk olarak Yetkilendirme filtreleri çalışır ve kullanıcının istek için yetkilendirilip yetkilendirilmediğini tespit etmek için kullanılır. Yetkilendirme filtreleri, istek yetkilendirilmezse işlem hattı kısa devre dışı olur.

  • Kaynak filtreleri:

    • Yetkilendirmeden sonra çalıştırın.
    • OnResourceExecuting Filtre işlem hattının geri kalanında kodu çalıştırır. Örneğin, OnResourceExecuting model bağlamadan önce kodu çalıştırır.
    • OnResourceExecuted ardışık düzenin geri kalanı tamamlandıktan sonra kodu çalıştırır.
  • Eylem filtreleri:

    • Kodu bir eylem yöntemi çağrıldıktan hemen önce ve sonra çalıştırın.
    • Bir eyleme geçirilen bağımsız değişkenleri değiştirebilir.
    • Eylemden döndürülen sonucu değiştirebilir.
    • Sayfalarda desteklenmez Razor .
  • Özel durum filtreleri , yanıt gövdesinin üzerine yazılmadan önce oluşan işlenmemiş özel durumlara genel ilkeler uygular.

  • Sonuç filtreleri , eylem sonuçlarının yürütülmesinden hemen önce ve sonra kodu çalıştırır. Bunlar yalnızca eylem yöntemi başarıyla yürütüldüğünde çalışır. Bu değerler, görünüm veya biçimlendirici yürütmesinin yürütülmesi gereken mantık için faydalıdır.

Aşağıdaki diyagramda filtre türlerinin filtre ardışık düzeninde nasıl etkileşimde bulunduğu gösterilmektedir.

İstek, Yetkilendirme filtreleri, kaynak filtreleri, model bağlama, eylem filtreleri, eylem yürütme ve eylem sonucu dönüştürme, özel durum filtreleri, sonuç filtreleri ve sonuç yürütmesi aracılığıyla işlenir. Bu şekilde, istek yalnızca istemciye gönderilen yanıt haline gelmeden önce sonuç filtreleri ve kaynak filtreleri tarafından işlenir.

Uygulama

Filtreler, farklı arabirim tanımları aracılığıyla hem zaman uyumlu hem de zaman uyumsuz uygulamaları destekler.

Zaman uyumlu filtreler, ardışık düzen aşamasından önce ve sonra kodu çalıştırır. Örneğin, OnActionExecuting eylem yöntemi çağrılmadan önce çağrılır. OnActionExecuted , eylem yöntemi döndüğünde çağrılır.

public class MySampleActionFilter : IActionFilter 
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), context.HttpContext.Request.Path);
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), context.HttpContext.Request.Path);
    }
}

Önceki kodda, Mydebug , örnek indirmadabir yardımcı programdır.

Zaman uyumsuz filtreler bir On-Stage-ExecutionAsync yöntemi tanımlar. Örneğin OnActionExecutionAsync :

public class SampleAsyncActionFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(
        ActionExecutingContext context,
        ActionExecutionDelegate next)
    {
        // Do something before the action executes.

        // next() calls the action method.
        var resultContext = await next();
        // resultContext.Result is set.
        // Do something after the action executes.
    }
}

Önceki kodda,, SampleAsyncActionFilter ActionExecutionDelegate next Action metodunu yürüten bir () içerir.

Birden çok filtre aşaması

Birden çok filtre aşaması için arabirimler tek bir sınıfta uygulanabilir. Örneğin, ActionFilterAttribute sınıfı şunları uygular:

Her ikisini de değil , bir filtre arabiriminin zaman uyumlu veya zaman uyumsuz sürümünü uygulayın. Çalışma zamanı öncelikle filtrenin zaman uyumsuz arabirimi uygulayıp uygulamadığını denetler ve bu durumda bunu çağırır. Aksi takdirde, zaman uyumlu arabirimin Yöntem (ler) i çağırır. Tek bir sınıfta hem zaman uyumsuz hem de zaman uyumlu arabirimler uygulanmışsa, yalnızca zaman uyumsuz yöntem çağrılır. Gibi soyut sınıflar kullanırken ActionFilterAttribute , yalnızca zaman uyumlu yöntemleri veya her bir filtre türü için zaman uyumsuz yöntemleri geçersiz kılın.

Yerleşik filtre öznitelikleri

ASP.NET Core, alt sınıflanmış ve özelleştirilebilen yerleşik öznitelik tabanlı filtreler içerir. Örneğin, aşağıdaki sonuç filtresi yanıta bir üst bilgi ekler:

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 });
        base.OnResultExecuting(context);
    }
}

Öznitelikler, önceki örnekte gösterildiği gibi, filtrelerin bağımsız değişkenleri kabul etmesine izin verir. ' İ AddHeaderAttribute bir denetleyiciye veya eylem yöntemine uygulayın ve http üstbilgisinin adını ve değerini belirtin:

[AddHeader("Author", "Rick Anderson")]
public class SampleController : Controller
{
    public IActionResult Index()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }

Üst bilgileri incelemek için tarayıcı geliştirici araçları gibi bir araç kullanın. Yanıt üst bilgileri altında author: Rick Anderson görüntülenir.

Aşağıdaki kod şunları uygular ActionFilterAttribute :

  • Yapılandırma sistemindeki başlığı ve adı okur. Önceki örnekten farklı olarak, aşağıdaki kod koda filtre parametrelerinin eklenmesine gerek yoktur.
  • Başlık ve adı yanıt üstbilgisine ekler.
public class MyActionFilterAttribute : ActionFilterAttribute
{
    private readonly PositionOptions _settings;

    public MyActionFilterAttribute(IOptions<PositionOptions> options)
    {
        _settings = options.Value;
        Order = 1;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.Headers.Add(_settings.Title, 
                                                 new string[] { _settings.Name });
        base.OnResultExecuting(context);
    }
}

Yapılandırma seçenekleri, Seçenekler desenininkullanıldığı yapılandırma sisteminden sağlanır. Örneğin, appsettings.json dosyasından:

{
  "Position": {
    "Title": "Editor",
    "Name": "Joe Smith"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

İçinde StartUp.ConfigureServices :

  • PositionOptionsSınıfı, yapılandırma alanı ile hizmet kapsayıcısına eklenir "Position" .
  • , MyActionFilterAttribute Hizmet kapsayıcısına eklenir.
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<PositionOptions>(
             Configuration.GetSection("Position"));
    services.AddScoped<MyActionFilterAttribute>();

    services.AddControllersWithViews();
}

Aşağıdaki kod, sınıfını göstermektedir PositionOptions :

public class PositionOptions
{
    public string Title { get; set; }
    public string Name { get; set; }
}

Aşağıdaki kod MyActionFilterAttribute yöntemi için geçerlidir Index2 :

[AddHeader("Author", "Rick Anderson")]
public class SampleController : Controller
{
    public IActionResult Index()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }

    [ServiceFilter(typeof(MyActionFilterAttribute))]
    public IActionResult Index2()
    {
        return Content("Header values by configuration.");
    }

Yanıt üst bilgileri altında author: Rick Anderson , ve Editor: Joe Smith Sample/Index2 uç nokta çağrıldığında görüntülenir.

Aşağıdaki kod, MyActionFilterAttribute ve AddHeaderAttribute Razor sayfasını sayfasına uygular:

[AddHeader("Author", "Rick Anderson")]
[ServiceFilter(typeof(MyActionFilterAttribute))]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}

Filtreler Razor sayfa işleyici yöntemlerine uygulanamaz. Bunlar Razor sayfa modeline ya da genel olarak uygulanabilir.

Filtre arabirimlerinden birkaçı, özel uygulamalar için temel sınıflar olarak kullanılabilecek karşılık gelen özniteliklere sahiptir.

Filtre öznitelikleri:

Kapsamları ve yürütme sırasını filtrele

Üç kapsamından birindeki işlem hattına bir filtre eklenebilir:

  • Bir denetleyici eyleminde bir özniteliği kullanma. Filtre öznitelikleri, Razor sayfa işleyici yöntemlerine uygulanamaz.
  • Bir denetleyici veya sayfada bir özniteliği kullanma Razor .
  • Aşağıdaki kodda gösterildiği gibi tüm denetleyiciler, Eylemler ve sayfalar için genel olarak Razor :
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(options =>
   {
        options.Filters.Add(typeof(MySampleActionFilter));
    });
}

Varsayılan yürütme sırası

İşlem hattının belirli bir aşamasına ilişkin birden çok filtre olduğunda, kapsam varsayılan filtre yürütme sırasını belirler. Genel filtreler kapsayan sınıf filtreleri, bu da kapsayan Yöntem filtreleri.

Filtre iç içe geçme sonucu olarak, filtrenin kodu, önceki kodun ters sırasına göre çalışır. Filtre sırası:

  • Genel filtrelerin önceki kodu.
    • Denetleyicinin ve sayfa filtrelerinin öncesindeki kodu Razor .
      • Eylem yöntemi filtresinin önceki kodu.
      • Eylem sonrası kodu yöntem filtreleri.
    • Denetleyicinin ve Sayfa filtrelerinin son Razor kodu.
  • Genel filtrelerin sonrası kodu.

Zaman uyumlu eylem filtreleri için filtre yöntemlerinin çağrılma sırası gösteren aşağıdaki örnek.

Sequence Filtre kapsamı Filter yöntemi
1 Genel OnActionExecuting
2 Denetleyici veya Razor Sayfa OnActionExecuting
3 Yöntem OnActionExecuting
4 Yöntem OnActionExecuted
5 Denetleyici veya Razor Sayfa OnActionExecuted
6 Genel OnActionExecuted

Denetleyici düzeyi filtreleri

Temel sınıftan devralan her Controller denetleyici , ve yöntemlerini Controller.OnActionExecuting Controller.OnActionExecutionAsync Controller.OnActionExecuted OnActionExecuted içerir. Bu yöntemler:

  • Belirli bir eylem için çalıştıran filtreleri sarmalar.
  • OnActionExecuting eylem filtrelerinin herhangi biri öncesinde çağrılır.
  • OnActionExecuted tüm eylem filtrelerinin ardından çağrılır.
  • OnActionExecutionAsync eylem filtrelerinin herhangi biri öncesinde çağrılır. Eylem yönteminin ardından next çalıştır çalıştır çalıştırktan sonra filtrede yer alan kod.

Örneğin, indirme örneğinde başlangıçta MySampleActionFilter genel olarak uygulanır.

: TestController

  • Eyleme SampleActionFilterAttribute [SampleActionFilter] () FilterTest2 uygular.
  • ve geçersiz OnActionExecuting OnActionExecuted kılmaları.
public class TestController : Controller
{
    [SampleActionFilter(Order = int.MinValue)]
    public IActionResult FilterTest2()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), HttpContext.Request.Path);
        base.OnActionExecuting(context);
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), HttpContext.Request.Path);
        base.OnActionExecuted(context);
    }
}

Mydisplayrouteınfo , Rick.Docs. Samples. routeınfo NuGet paketi tarafından sağlanır ve rota bilgilerini görüntüler.

'a giderek https://localhost:5001/Test/FilterTest2 aşağıdaki kodu çalıştırır:

  • TestController.OnActionExecuting
    • MySampleActionFilter.OnActionExecuting
      • SampleActionFilterAttribute.OnActionExecuting
        • TestController.FilterTest2
      • SampleActionFilterAttribute.OnActionExecuted
    • MySampleActionFilter.OnActionExecuted
  • TestController.OnActionExecuted

Denetleyici düzeyi filtreleri Order özelliğini olarak int.MinValue ayarlayın. Denetleyici düzeyi filtreleri, yöntemlere filtre uygulandıktan sonra çalıştıracak şekilde ayarlanmaz. Sipariş, sonraki bölümde açıklanmıştır.

Sayfalar Razor için bkz. Razor Filtre yöntemlerini geçersiz karak Sayfa filtrelerini uygulama.

Varsayılan sırayı geçersiz kılma

Varsayılan yürütme sırası uygulanarak geçersiz IOrderedFilter kılınabilir. IOrderedFilter yürütme sırası Order belirlemek için kapsamdan öncelikli olan özelliğini ortaya çıkarır. Daha düşük değere sahip Order bir filtre:

  • daha yüksek değerine sahip bir filtreden önceki kodunu Order çalıştırır.
  • Daha yüksek bir değere sahip bir filtreden sonra gelen kodunu Order çalıştırır.

özelliği Order bir oluşturucu parametresiyle ayarlanır:

[SampleActionFilter(Order = int.MinValue)]

Aşağıdaki denetleyicide iki eylem filtrelerini düşünün:

[MyAction2Filter]
public class Test2Controller : Controller
{
    public IActionResult FilterTest2()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), HttpContext.Request.Path);
        base.OnActionExecuting(context);
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), HttpContext.Request.Path);
        base.OnActionExecuted(context);
    }
}

içinde genel bir filtre StartUp.ConfigureServices eklenir:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(options =>
   {
        options.Filters.Add(typeof(MySampleActionFilter));
    });
}

3 filtre aşağıdaki sırayla çalıştırabilirsiniz:

  • Test2Controller.OnActionExecuting
    • MySampleActionFilter.OnActionExecuting
      • MyAction2FilterAttribute.OnActionExecuting
        • Test2Controller.FilterTest2
      • MyAction2FilterAttribute.OnResultExecuting
    • MySampleActionFilter.OnActionExecuted
  • Test2Controller.OnActionExecuted

özelliği Order filtrelerin çalışma sırası belirlenirken kapsamı geçersiz kılar. Filtreler önce sıralamaya göre sıralanmış, ardından kapsam da bağlarını bozmak için kullanılır. Tüm yerleşik filtreler uygulanır ve IOrderedFilter varsayılan değeri Order 0 olarak ayarlar. Daha önce belirtildiği gibi denetleyici düzeyi filtreleri Order özelliğini Yerleşik filtreler için olarak ayarlamaktadır. Kapsam, sıfır olmayan bir değere ayarlanmadıkça int.MinValue Order sıralamayı belirler.

Yukarıdaki kodda, MySampleActionFilter genel kapsamına sahip olduğu için denetleyici kapsamı olan MyAction2FilterAttribute 'den önce çalışır. İlk MyAction2FilterAttribute çalıştırmayı yapmak için sırayı olarak int.MinValue ayarlayın:

[MyAction2Filter(int.MinValue)]
public class Test2Controller : Controller
{
    public IActionResult FilterTest2()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), HttpContext.Request.Path);
        base.OnActionExecuting(context);
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), HttpContext.Request.Path);
        base.OnActionExecuted(context);
    }
}

İlk olarak genel filtrenin MySampleActionFilter çalışması için olarak Order int.MinValue ayarlayın:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(options =>
   {
        options.Filters.Add(typeof(MySampleActionFilter),
                            int.MinValue);
    });
}

İptal ve kısa devre

Filtre işlem hattı, sağlanan parametrenin özelliği filtre Result yöntemine ResourceExecutingContext ayarlanacak şekilde kısa devreye sahip olabilir. Örneğin, aşağıdaki Kaynak filtresi işlem hattının geri kalanının yürütülmesini önler:

public class ShortCircuitingResourceFilterAttribute : Attribute, IResourceFilter
{
    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        context.Result = new ContentResult()
        {
            Content = "Resource unavailable - header not set."
        };
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
    }
}

Aşağıdaki kodda hem hem ShortCircuitingResourceFilter de filtresi eylem yöntemini AddHeader SomeResource hedefler. : ShortCircuitingResourceFilter

  • İlk olarak çalışır çünkü bu bir Kaynak Filtresidir ve AddHeader bir Eylem Filtresidir.
  • İşlem hattının geri kalanını kısa devreler.

Bu nedenle AddHeader filtre eylem için hiçbir zaman SomeResource çalıştırılamaz. Bu davranış, her iki filtre de eylem yöntemi düzeyinde uygulanmışsa, ilk olarak çalışma sağlanırsa ShortCircuitingResourceFilter aynı olur. , ShortCircuitingResourceFilter önce filtre türü nedeniyle veya özelliğin açıkça kullanımıyla Order çalışır.

[AddHeader("Author", "Rick Anderson")]
public class SampleController : Controller
{
    public IActionResult Index()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }

    [ServiceFilter(typeof(MyActionFilterAttribute))]
    public IActionResult Index2()
    {
        return Content("Header values by configuration.");
    }

    [ShortCircuitingResourceFilter]
    public IActionResult SomeResource()
    {
        return Content("Successful access to resource - header is set.");
    }

    [AddHeaderWithFactory]
    public IActionResult HeaderWithFactory()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }
}

Bağımlılık ekleme

Filtreler türe veya örneğine göre eklenebilir. Bir örnek eklenirse, bu örnek her istek için kullanılır. Bir tür eklenirse, tür etkinleştirilmiş olur. Tür tarafından etkinleştirilmiş bir filtre şu anlama gelir:

  • Her istek için bir örnek oluşturulur.
  • Tüm oluşturucu bağımlılıkları bağımlılık ekleme (DI) ile doldurulur.

Öznitelik olarak uygulanan ve doğrudan denetleyici sınıflarına veya eylem yöntemlerine eklenen filtreler, bağımlılık ekleme (DI) tarafından sağlanan oluşturucu bağımlılıklarına sahip olamaz. Oluşturucu bağımlılıkları DI tarafından sağlanamıyor çünkü:

  • Özniteliklerin uygulandığı yerde oluşturucu parametreleri sağlanmalıdır.
  • Bu, özniteliklerin çalışmayla ilgili bir sınırlamadır.

Aşağıdaki filtreler DI'den sağlanan oluşturucu bağımlılıklarını destekler:

Yukarıdaki filtreler bir denetleyiciye veya eylem yöntemine uygulanabilir:

Günlükler DI'den kullanılabilir. Ancak, yalnızca günlük amacıyla filtre oluşturmaktan ve kullanmaktan kaçının. Yerleşik çerçeve günlüğü genellikle günlüğe kaydetme için gerekenleri sağlar. Filtrelere eklenen günlük kaydı:

  • İşletme etki alanı sorunlarına veya filtreye özgü davranışa odaklanması gerekir.
  • Eylemleri veya diğer çerçeve olaylarını günlüğe kaydedilir. Yerleşik filtre günlük eylemlerini ve çerçeve olaylarını filtreler.

ServiceFilterAttribute

Hizmet filtresi uygulama türleri içinde ConfigureServices kaydedilir. , ServiceFilterAttribute DI'den filtrenin bir örneğini alın.

Aşağıdaki kod şunları AddHeaderResultServiceFilter gösterir:

public class AddHeaderResultServiceFilter : IResultFilter
{
    private ILogger _logger;
    public AddHeaderResultServiceFilter(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<AddHeaderResultServiceFilter>();
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        var headerName = "OnResultExecuting";
        context.HttpContext.Response.Headers.Add(
            headerName, new string[] { "ResultExecutingSuccessfully" });
        _logger.LogInformation("Header added: {HeaderName}", headerName);
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // Can't add to headers here because response has started.
        _logger.LogInformation("AddHeaderResultServiceFilter.OnResultExecuted");
    }
}

Aşağıdaki AddHeaderResultServiceFilter kodda, DI kapsayıcısı eklenir:

public void ConfigureServices(IServiceCollection services)
{
    // Add service filters.
    services.AddScoped<AddHeaderResultServiceFilter>();
    services.AddScoped<SampleActionFilterAttribute>();

    services.AddControllersWithViews(options =>
   {
       options.Filters.Add(new AddHeaderAttribute("GlobalAddHeader",
           "Result filter added to MvcOptions.Filters"));         // An instance
        options.Filters.Add(typeof(MySampleActionFilter));         // By type
        options.Filters.Add(new SampleGlobalActionFilter());       // An instance
    });
}

Aşağıdaki kodda, ServiceFilter özniteliği DI'den filtrenin AddHeaderResultServiceFilter bir örneğini almaktadır:

[ServiceFilter(typeof(AddHeaderResultServiceFilter))]
public IActionResult Index()
{
    return View();
}

kullanırken ServiceFilterAttribute ayarını: ServiceFilterAttribute.IsReusable

  • Filtre örneğinin, içinde oluşturulan istek kapsamının dışında yeniden kullanılana dair bir ipucu sağlar. ASP.NET Core çalışma zamanı şunları garanti etmez:

    • Filtrenin tek bir örneği oluşturulacak.
    • Filtre daha sonra DI kapsayıcısı tarafından yeniden istekte olmayacaktır.
  • Tekliden farklı bir yaşam süresine sahip hizmetlere bağlı olan bir filtre ile kullanılmamalı.

ServiceFilterAttribute , 'i uygulamaya IFilterFactory almaktadır. IFilterFactory , örnek CreateInstance oluşturmak için yöntemini ortaya IFilterMetadata çıkarır. CreateInstance belirtilen türü DI'den yükler.

TypeFilterAttribute

TypeFilterAttribute benzerdir ServiceFilterAttribute , ancak türü doğrudan dı kapsayıcısından çözümlenmez. Kullanarak türü başlatır Microsoft.Extensions.DependencyInjection.ObjectFactory .

TypeFilterAttributeTürler doğrudan dı kapsayıcısından çözümlenmediğinden:

  • ' İ kullanılarak başvurulan türlerin, TypeFilterAttribute dı kapsayıcısına kayıtlı olması gerekmez. Bunların bağımlılıkları, dı kapsayıcısı tarafından yerine getirilir.
  • TypeFilterAttribute isteğe bağlı olarak tür için Oluşturucu bağımsız değişkenlerini kabul edebilir.

Kullanırken TypeFilterAttribute , ayarı TypeFilterAttribute.IsReusable :

  • Filtre örneğinin, içinde oluşturulduğu istek kapsamının dışında yeniden kullanılabilir olabileceği ipucu sağlar. ASP.NET Core çalışma zamanı, filtrenin tek bir örneğinin oluşturulacağı garantisi vermez.

  • Tek bir yaşam süresine sahip hizmetlere bağımlı olan bir filtreyle kullanılmamalıdır.

Aşağıdaki örnek kullanarak bir türe bağımsız değişkenlerin nasıl geçirileceğini göstermektedir TypeFilterAttribute :

[TypeFilter(typeof(LogConstantFilter),
    Arguments = new object[] { "Method 'Hi' called" })]
public IActionResult Hi(string name)
{
    return Content($"Hi {name}");
}

Yetkilendirme filtreleri

Yetkilendirme filtreleri:

  • , Filtre ardışık düzeninde ilk filtrelerin çalıştırılmasıyla sonuçlanır.
  • Eylem yöntemlerine erişimi denetleyin.
  • Bir Before yöntemi, ancak After yönteminden hiçbiri.

Özel Yetkilendirme filtreleri özel bir yetkilendirme çerçevesi gerektirir. Özel bir filtre yazmak için yetkilendirme ilkelerini yapılandırmayı veya özel bir yetkilendirme ilkesi yazmayı tercih edin. Yerleşik yetkilendirme filtresi:

  • Yetkilendirme sistemini çağırır.
  • İstekleri yetkilendirmez.

Yetkilendirme filtreleri içinde özel durumlar atamayın:

  • Özel durum işlenmeyecektir.
  • Özel durum filtreleri özel durumu işleymeyecektir.

Bir yetkilendirme filtresinde özel durum oluştuğunda bir sınama vermeyi düşünün.

Yetkilendirmehakkında daha fazla bilgi edinin.

Kaynak filtreleri

Kaynak filtreleri:

Kaynak filtreleri, işlem hattının büyük bir yanındaki kısa devre için faydalıdır. Örneğin, bir önbelleğe alma filtresi, bir önbellek isabetinden ardışık düzen geri kalanından kaçınabilir.

Kaynak filtresi örnekleri:

Eylem filtreleri

Eylem filtreleri sayfalara uygulanmaz Razor . Razor Sayfalar IPageFilter ve destekler IAsyncPageFilter . Daha fazla bilgi için bkz. Razor sayfalar için filtre yöntemleri.

Eylem filtreleri:

Aşağıdaki kod bir örnek eylem filtresi gösterir:

public class MySampleActionFilter : IActionFilter 
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), context.HttpContext.Request.Path);
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
        MyDebug.Write(MethodBase.GetCurrentMethod(), context.HttpContext.Request.Path);
    }
}

, ActionExecutingContext Aşağıdaki özellikleri sağlar:

  • ActionArguments -girişlerin bir eylem yöntemine okunmasını sağlar.
  • Controller -denetleyici örneğinin işlenmesine izin vermez.
  • Result - Result eylem yönteminin ve sonraki eylem filtrelerinin kısa devre dışı yürütülmesi ayarlanıyor.

Eylem yönteminde özel durum oluşturma:

  • Sonraki filtrelerin çalıştırılmasını önler.
  • Ayarından farklı olarak Result , başarılı bir sonuç yerine başarısızlık olarak değerlendirilir.

, ActionExecutedContext Controller Ve Result ek olarak aşağıdaki özellikleri sağlar:

  • Canceled -Eylem yürütmesi başka bir filtre tarafından kabul edilse true.

  • Exception -Eylem veya daha önce çalıştırılan eylem filtresi bir özel durum oluşturdu-null değil. Bu özellik null olarak ayarlanıyor:

    • Özel durumu etkin bir şekilde işler.
    • Result eylem yönteminden döndürülmüş gibi yürütülür.

Bir için IAsyncActionFilter bir çağrısı ActionExecutionDelegate :

  • Sonraki eylem filtrelerini ve eylem yöntemini yürütür.
  • ActionExecutedContext döndürür.

Kısa devre dışı, Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext.Result bir sonuç örneğine atayın ve çağırmayın next ( ActionExecutionDelegate ).

Çerçeve, alt sınıflı olabilecek bir Özet sağlar ActionFilterAttribute .

OnActionExecutingEylem filtresi şu şekilde kullanılabilir:

  • Model durumunu doğrulayın.
  • Durum geçersizse bir hata döndürür.
public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext 
                                           context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(
                                                context.ModelState);
        }
    }

Not

Öznitelik ile ek açıklama eklenmiş denetleyiciler [ApiController] model durumunu otomatik olarak doğrular ve bir 400 yanıtı döndürür. Daha fazla bilgi için bkz. OTOMATIK HTTP 400 yanıtları.

OnActionExecutedYöntemi eylem yönteminden sonra çalışır:

  • Ve, özelliği aracılığıyla eylemin sonuçlarını görebilir ve değiştirebilir Result .

  • Canceled eylem yürütmesi başka bir filtre tarafından kabul edilse, true olarak ayarlanır.

  • Exception eylem veya sonraki bir eylem filtresi bir özel durum harekete geçirdi null olmayan bir değer olarak ayarlanır. ExceptionNull olarak ayarlanıyor:

    • Bir özel durumu etkin bir şekilde işler.
    • ActionExecutedContext.Result eylem yönteminden normal olarak döndürülmüş gibi yürütülür.
public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext 
                                           context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(
                                                context.ModelState);
        }
    }


    public override void OnActionExecuted(ActionExecutedContext 
                                          context)
    {
        var result = context.Result;
        // Do something with Result.
        if (context.Canceled == true)
        {
            // Action execution was short-circuited by another filter.
        }

        if(context.Exception != null)
        {
            // Exception thrown by action or action filter.
            // Set to null to handle the exception.
            context.Exception = null;
        }
        base.OnActionExecuted(context);
    }
}

Özel durum filtreleri

Özel durum filtreleri:

Aşağıdaki örnek özel durum filtresi, uygulama geliştirmede olduğunda oluşan özel durumlar hakkındaki ayrıntıları görüntülemek için özel bir hata görünümü kullanır:

public class CustomExceptionFilter : IExceptionFilter
{
    private readonly IWebHostEnvironment _hostingEnvironment;
    private readonly IModelMetadataProvider _modelMetadataProvider;

    public CustomExceptionFilter(
        IWebHostEnvironment hostingEnvironment,
        IModelMetadataProvider modelMetadataProvider)
    {
        _hostingEnvironment = hostingEnvironment;
        _modelMetadataProvider = modelMetadataProvider;
    }

    public void OnException(ExceptionContext context)
    {
        if (!_hostingEnvironment.IsDevelopment())
        {
            return;
        }
        var result = new ViewResult {ViewName = "CustomError"};
        result.ViewData = new ViewDataDictionary(_modelMetadataProvider,
                                                    context.ModelState);
        result.ViewData.Add("Exception", context.Exception);
        // TODO: Pass additional detailed data via ViewData
        context.Result = result;
    }
}

Aşağıdaki kod özel durum filtresini sınar:

[TypeFilter(typeof(CustomExceptionFilter))]
public class FailingController : Controller
{
    [AddHeader("Failing Controller", 
               "Won't appear when exception is handled")]
    public IActionResult Index()
    {
        throw new Exception("Testing custom exception filter.");
    }
}

Özel durum filtreleri:

  • Etkinlikden önceki ve sonraki olaylar yok.
  • OnExceptionVeya uygulayın OnExceptionAsync .
  • RazorSayfa veya denetleyici oluşturma, model bağlama, eylem filtreleri veya eylem yöntemlerinde oluşan işlenmemiş özel durumları işleyin.
  • Kaynak filtrelerinde, sonuç filtrelerinde veya MVC sonuç yürütülürken oluşan özel durumları yakalamayın .

Bir özel durumu işlemek için, ExceptionHandled özelliğini true bir yanıt olarak ayarlayın veya yazın. Bu, özel durumun yayılmasını engeller. Özel durum filtresi bir özel durumu "başarılı" olarak açamaz. Yalnızca bir eylem filtresi bunu yapabilir.

Özel durum filtreleri:

  • Eylemler içinde oluşan özel durumları yakalamaya uygundur.
  • , Hata işleme ara yazılımı olarak esnek değildir.

Özel durum işleme için ara yazılımı tercih edin. Yalnızca hata işlemenin hangi eylem yöntemine göre farklılık gösteren özel durum filtrelerini kullanın. Örneğin, bir uygulama hem API uç noktaları hem de görünümler/HTML için eylem yöntemlerine sahip olabilir. API uç noktaları, hata bilgilerini JSON olarak döndürebilir, ancak görünüm tabanlı eylemler bir hata sayfasını HTML olarak döndürebilir.

Sonuç filtreleri

Sonuç filtreleri:

IResultFilter ve IAsyncResultFilter

Aşağıdaki kod, HTTP üst bilgisi ekleyen bir sonuç filtresini gösterir:

public class AddHeaderResultServiceFilter : IResultFilter
{
    private ILogger _logger;
    public AddHeaderResultServiceFilter(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<AddHeaderResultServiceFilter>();
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        var headerName = "OnResultExecuting";
        context.HttpContext.Response.Headers.Add(
            headerName, new string[] { "ResultExecutingSuccessfully" });
        _logger.LogInformation("Header added: {HeaderName}", headerName);
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // Can't add to headers here because response has started.
        _logger.LogInformation("AddHeaderResultServiceFilter.OnResultExecuted");
    }
}

Yürütülen sonuç türü, eyleme bağlıdır. Görünüm döndüren eylem, yürütülen işleminin bir parçası olarak tüm razor ViewResult işlemeyi içerir. API yöntemi, sonucun yürütülmesinin bir parçası olarak bazı serileştirmeler gerçekleştirebilirsiniz. Eylem sonuçları hakkında daha fazla bilgi.

Sonuç filtreleri yalnızca bir eylem veya eylem filtresi eylem sonucu ürettiği zaman yürütülür. Sonuç filtreleri şu zaman yürütülmez:

  • Yetkilendirme filtresi veya kaynak filtresi işlem hattını kısa devreler.
  • Özel durum filtresi, bir eylem sonucu üreterek bir özel durumu işler.

yöntemi, Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuting olarak ayararak eylem sonucu ve sonraki sonuç filtrelerinin kısa devre yürütmesini devre dışı Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext.Cancel true bırakır. Boş yanıt oluşturmamak için kısa bağlantı hattı kullanılırken yanıt nesnesine yazın. içinde özel durum IResultFilter.OnResultExecuting oluşturur:

  • Eylem sonucu ve izleyen filtrelerin yürütülmesini önler.
  • Başarılı bir sonuç yerine hata olarak kabul edilir.

Yöntem Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuted çalıştır geldiğinde yanıt büyük olasılıkla istemciye zaten gönderilmiştir. Yanıt istemciye zaten gönderilmişse değiştirilemez.

ResultExecutedContext.Canceled , eylem sonucu true yürütmenin başka bir filtre tarafından kısa devresi varsa olarak ayarlanır.

ResultExecutedContext.Exception eylem sonucu veya sonraki bir sonuç filtresi bir özel durum oluşturdu ise null olmayan bir değere ayarlanır. null olarak ayarlanırsa bir özel durum etkili bir şekilde işlenebilir ve özel durumun işlem Exception hattında daha sonra yeniden atması önlenebilir. Sonuç filtresinde bir özel durum işlenmişken yanıta veri yazmanın güvenilir bir yolu yoktur. Bir eylem sonucu özel durum ortaya çıkan üst bilgiler istemciye boşaltıldısa, hata kodu göndermek için güvenilir bir mekanizma yoktur.

için, IAsyncResultFilter üzerinde await next çağrısı, sonraki tüm sonuç ResultExecutionDelegate filtrelerini ve eylem sonucu yürütür. Kısa devre için olarak ResultExecutingContext.Cancel ayarlayın true ve çağrısına gerek ResultExecutionDelegate yok:

public class MyAsyncResponseFilter : IAsyncResultFilter
{
    public async Task OnResultExecutionAsync(ResultExecutingContext context,
                                             ResultExecutionDelegate next)
    {
        if (!(context.Result is EmptyResult))
        {
            await next();
        }
        else
        {
            context.Cancel = true;
        }

    }
}

Çerçeve, alt ResultFilterAttribute sınıflandırılan bir soyutlama sağlar. Daha önce gösterilen AddHeaderAttribute sınıfı bir sonuç filtresi özniteliği örneğidir.

IAlwaysRunResultFilter ve IAsyncAlwaysRunResultFilter

ve IAlwaysRunResultFilter IAsyncAlwaysRunResultFilter arabirimleri, tüm IResultFilter eylem sonuçları için çalışan bir uygulama belirtir. Bu, aşağıdakiler tarafından üretilen eylem sonuçlarını içerir:

  • Yetkilendirme filtreleri ve bu kısa devreyi kaynak filtreleri.
  • Özel durum filtreleri.

Örneğin, aşağıdaki filtre her zaman çalışır ve içerik anlaşması başarısız olduğunda ObjectResult 422 İşlenebilir Olmayan Varlık durum koduyla bir eylem sonucu ( ) ayarlar:

public class UnprocessableResultFilter : Attribute, IAlwaysRunResultFilter
{
    public void OnResultExecuting(ResultExecutingContext context)
    {
        if (context.Result is StatusCodeResult statusCodeResult &&
            statusCodeResult.StatusCode == (int) HttpStatusCode.UnsupportedMediaType)
        {
            context.Result = new ObjectResult("Can't process this!")
            {
                StatusCode = (int) HttpStatusCode.UnsupportedMediaType,
            };
        }
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
    }
}

IFilterFactory

IFilterFactory , 'i uygulamaya IFilterMetadata almaktadır. Bu nedenle IFilterFactory örnek, filtre işlem hattının IFilterMetadata herhangi bir yerinde örnek olarak kullanılabilir. Çalışma zamanı filtreyi çağırmaya hazır olduğunda, filtreyi bir 'ye attırma girişiminde IFilterFactory bulunmaktadır. Bu oluşturma başarılı CreateInstance olursa, çağrılan örneği oluşturmak IFilterMetadata için yöntemi çağrılır. Bu esnek bir tasarım sağlar çünkü uygulama başlatıldığında kesin filtre işlem hattının açıkça ayarlanmış olması gerekmez.

IFilterFactory.IsReusable:

  • Fabrika tarafından oluşturulan filtre örneğinin, içinde oluşturulan istek kapsamının dışında yeniden kullanılagely dair bir ipucu olabilir.
  • Tekliden farklı bir yaşam süresine sahip hizmetlere bağlı olan bir filtre ile kullanılmamalı.

ASP.NET Core çalışma zamanı şunları garanti etmez:

  • Filtrenin tek bir örneği oluşturulacak.
  • Filtre daha sonra DI kapsayıcısı tarafından yeniden istekte olmayacaktır.

Uyarı

Yalnızca filtrelerin kaynağı belirsizse, filtreler durum bilgisizse ve filtrelerin birden çok HTTP isteği arasında kullanımı güvenli ise, bu şekilde IFilterFactory.IsReusable true yapılandırabilirsiniz. Örneğin, kapsam kapsamında veya döndürürse geçici olarak kaydedilen DI'den filtre IFilterFactory.IsReusable true döndürebilirsiniz.

IFilterFactory filtre oluşturmaya yönelik başka bir yaklaşım olarak özel öznitelik uygulamaları kullanılarak uygulanabilirsiniz:

public class AddHeaderWithFactoryAttribute : Attribute, IFilterFactory
{
    // Implement IFilterFactory
    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        return new InternalAddHeaderFilter();
    }

    private class InternalAddHeaderFilter : IResultFilter
    {
        public void OnResultExecuting(ResultExecutingContext context)
        {
            context.HttpContext.Response.Headers.Add(
                "Internal", new string[] { "My header" });
        }

        public void OnResultExecuted(ResultExecutedContext context)
        {
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Filtre aşağıdaki koda uygulanır:

[AddHeader("Author", "Rick Anderson")]
public class SampleController : Controller
{
    public IActionResult Index()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }

    [ServiceFilter(typeof(MyActionFilterAttribute))]
    public IActionResult Index2()
    {
        return Content("Header values by configuration.");
    }

    [ShortCircuitingResourceFilter]
    public IActionResult SomeResource()
    {
        return Content("Successful access to resource - header is set.");
    }

    [AddHeaderWithFactory]
    public IActionResult HeaderWithFactory()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }
}

İndirme örneğini çalıştırarak önceki kodu test edin:

  • F12 geliştirici araçlarını çağırma.
  • https://localhost:5001/Sample/HeaderWithFactory sayfasına gidin.

F12 geliştirici araçları, örnek kod tarafından eklenen aşağıdaki yanıt üst bilgilerini görüntüler:

  • yazar:Rick Anderson
  • globaladdheader:Result filter added to MvcOptions.Filters
  • iç:My header

Yukarıdaki kod internal: My header response üst bilgisini oluşturur.

Bir öznitelikte uygulanan IFilterFactory

Uygulayan IFilterFactory filtreler, şu filtreler için yararlıdır:

  • Parametre geçirmeyi gerektirmez.
  • DI tarafından doldurulması gereken oluşturucu bağımlılıkları vardır.

TypeFilterAttribute , 'i uygulamaya IFilterFactory almaktadır. IFilterFactory , örnek CreateInstance oluşturmak için yöntemini ortaya IFilterMetadata çıkarır. CreateInstance , belirtilen türü hizmetler kapsayıcısı (DI) ile yükler.

public class SampleActionFilterAttribute : TypeFilterAttribute
{
    public SampleActionFilterAttribute()
                         :base(typeof(SampleActionFilterImpl))
    { 
    }

    private class SampleActionFilterImpl : IActionFilter
    {
        private readonly ILogger _logger;
        public SampleActionFilterImpl(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<SampleActionFilterAttribute>();
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
           _logger.LogInformation("SampleActionFilterAttribute.OnActionExecuting");
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            _logger.LogInformation("SampleActionFilterAttribute.OnActionExecuted");
        }
    }
}

Aşağıdaki kod, uygulamak için üç yaklaşım [SampleActionFilter] gösterir:

[SampleActionFilter]
public IActionResult FilterTest()
{
    return Content("From FilterTest");
}

[TypeFilter(typeof(SampleActionFilterAttribute))]
public IActionResult TypeFilterTest()
{
    return Content("From TypeFilterTest");
}

// ServiceFilter must be registered in ConfigureServices or
// System.InvalidOperationException: No service for type '<filter>'
// has been registered. Is thrown.
[ServiceFilter(typeof(SampleActionFilterAttribute))]
public IActionResult ServiceFilterTest()
{
    return Content("From ServiceFilterTest");
}

Yukarıdaki kodda yöntemini ile dekore [SampleActionFilter] etmek, uygulamak için tercih edilen yaklaşımdır. SampleActionFilter

Filtre işlem hattında ara yazılımı kullanma

Kaynak filtreleri ara yazılım gibi çalışır ve işlem hattında daha sonra gelen her şeyin yürütülmesini çevreler. Ancak filtreler, çalışma zamanının parçası olduğu için ara yazılımdan farklıdır ve bu da bağlam ve yapılara erişimleri olduğu anlamına gelir.

Ara yazılımı filtre olarak kullanmak için, filtre işlem hattına eklenecek ara yazılımı belirten Configure yöntemiyle bir tür oluşturun. Aşağıdaki örnek, bir istek için geçerli kültürü kurmak için yerelleştirme ara yazılımı kullanır:

public class LocalizationPipeline
{
    public void Configure(IApplicationBuilder applicationBuilder)
    {
        var supportedCultures = new[]
        {
            new CultureInfo("en-US"),
            new CultureInfo("fr")
        };

        var options = new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture(
                                       culture: "en-US", 
                                       uiCulture: "en-US"),
            SupportedCultures = supportedCultures,
            SupportedUICultures = supportedCultures
        };
        options.RequestCultureProviders = new[] 
            { new RouteDataRequestCultureProvider() {
                Options = options } };

        applicationBuilder.UseRequestLocalization(options);
    }
}

Ara yazılımı MiddlewareFilterAttribute çalıştırmak için kullanın:

[Route("{culture}/[controller]/[action]")]
[MiddlewareFilter(typeof(LocalizationPipeline))]
public IActionResult CultureFromRouteData()
{
    return Content(
          $"CurrentCulture:{CultureInfo.CurrentCulture.Name},"
        + $"CurrentUICulture:{CultureInfo.CurrentUICulture.Name}");
}

Ara yazılım filtreleri, filtre işlem hattının Kaynak filtreleri ile aynı aşamasında, model bağlamadan önce ve işlem hattının geri kalanından sonra çalıştır.

İş parçacığı güvenliği

Bir filtrenin örneğini içine, filtresi yerine iletirken, Add filtre tek bir Type filtredir ve iş parçacığı güvenli değildir.

Sonraki eylemler

Rick Larkin, Rick Anderson, Tom Dykstrave Steve Smith

Bu ASP.NET Core, istek işleme işlem hattındaki belirli aşamalardan önce veya sonra kodun çalışmasına olanak sağlar.

Yerleşik filtreler, şöyle görevleri işler:

  • Yetkilendirme (kullanıcının yetkilendirilen kaynaklara erişimini engelleme).
  • Yanıtı önbelleğe alma (önbelleğe alınmış bir yanıt dönmek için istek işlem hattının kısa devresini çalıştırma).

Çapraz kesme endişelerini işlemek için özel filtreler oluşturulabilir. Çapraz kesme endişelerinin örnekleri arasında hata işleme, önbelleğe alma, yapılandırma, yetkilendirme ve günlüğe kaydetme yer alır. Filtreler, kodun çoğaltılmasından kaçınabilir. Örneğin, hata işleme özel durum filtresi hata işlemeyi birleştirilmiş olabilir.

Bu belge Razor Sayfalar, API denetleyicileri ve görünümlere sahip denetleyiciler için geçerlidir.

Örneği görüntüleme veya indirme (indirme).

Filtreler nasıl çalışır?

Filtreler, bazen ASP.NET Core işlem hattı olarak da adlandırılan bir eylem çağırma işlem hattı içinde çalıştırılan filtrelerdir. Filtre işlem hattı, ASP.NET Core eylem seçdikten sonra çalışır.

İstek Diğer Ara Yazılım, Yönlendirme Ara Yazılımı, Eylem Seçimi ve eylem eylem ASP.NET Core işlem hattı aracılığıyla işlenir. İstek işleme, istemciye bir yanıt gönderilmeden önce Eylem Seçimi, Yönlendirme Ara Yazılımı ve çeşitli Diğer Ara Yazılım ile devam eder.

Filtre türleri

Her filtre türü, filtre işlem hattında farklı bir aşamada yürütülür:

  • Yetkilendirme filtreleri ilk olarak kullanılır ve kullanıcının istek için yetkilendirilip yetkilendiril olmadığını belirlemek için kullanılır. İstek yetkisizse yetkilendirme işlem hattının kısa devresini filtreler.

  • Kaynak filtreleri:

    • Yetkilendirmeden sonra çalıştırın.
    • OnResourceExecuting filtre işlem hattının geri kalanından önce kodu çalıştırabilir. Örneğin, model OnResourceExecuting bağlamadan önce kod çalıştırabilir.
    • OnResourceExecuted işlem hattının geri kalanı tamamlandıktan sonra kodu çalıştırabilir.
  • Eylem filtreleri, tek bir eylem yöntemi çağrılmadan hemen önce ve sonra kodu çalıştırabilir. Bunlar, bir eyleme geçirilen bağımsız değişkenleri ve eylemden döndürülen sonucu işlemek için kullanılabilir. Eylem filtreleri Sayfalar'da Razor desteklenmiyor.

  • Özel durum filtreleri, yanıt gövdesine herhangi bir şey yazmadan önce oluşan işlanmamış özel durumlara genel ilkeler uygulamak için kullanılır.

  • Sonuç filtreleri, tek tek eylem sonuçlarının yürütülmesinin hemen öncesinde ve sonrasında kodu çalıştırabilir. Yalnızca eylem yöntemi başarıyla yürütülürken çalıştırıldı. Bunlar, görünüm veya biçimlendiren yürütmeyi çevrelesi gereken mantık için kullanışlıdır.

Aşağıdaki diyagramda filtre türlerinin filtre işlem hattında nasıl etkileşim kurduğu gösterir.

İstek Yetkilendirme Filtreleri, Kaynak Filtreleri, Model Bağlama, Eylem Filtreleri, Eylem Yürütme ve Eylem Sonucu Dönüştürme, Özel Durum Filtreleri, Sonuç Filtreleri ve Sonuç Yürütme aracılığıyla işlenir. Bu arada istek, istemciye gönderilen yanıt haline gelmeden önce yalnızca Sonuç Filtreleri ve Kaynak Filtreleri tarafından işlenir.

Uygulama

Filtreler, farklı arabirim tanımları aracılığıyla hem zaman uyumlu hem de zaman uyumsuz uygulamaları destekler.

Zaman uyumlu filtreler, işlem hattı aşamasından On-Stage-Executing önce ( ) ve sonra ( ) kodu On-Stage-Executed çalıştırabilir. Örneğin, OnActionExecuting eylem yöntemi çağrılmadan önce çağrılır. OnActionExecuted , eylem yöntemi döndürdikten sonra çağrılır.

public class MySampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
    }
}

Zaman uyumsuz filtreler bir yöntem On-Stage-ExecutionAsync tanımlar:

public class SampleAsyncActionFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(
        ActionExecutingContext context,
        ActionExecutionDelegate next)
    {
        // Do something before the action executes.

        // next() calls the action method.
        var resultContext = await next();
        // resultContext.Result is set.
        // Do something after the action executes.
    }
}

Yukarıdaki kodda, SampleAsyncActionFilter eylem yöntemini ActionExecutionDelegate next yürüten bir () vardır. Yöntemlerin On-Stage-ExecutionAsync her biri, FilterType-ExecutionDelegate filtrenin işlem hattı aşamalarını yürüten bir alır.

Birden çok filtre aşamaları

Birden çok filtre aşamaları için arabirimler tek bir sınıfta uygulanabilirsiniz. Örneğin, sınıfı ActionFilterAttribute , IActionFilter ve bunların zaman uyumsuz IResultFilter eşdeğerlerini uygulanır.

Her ikisini birden değil, bir filtre arabiriminin zaman uyumlu veya zaman uyumsuz sürümünü uygulama. Çalışma zamanı önce filtrenin zaman uyumsuz arabirimi uygulayan bir uygulama olup olduğunu denetler ve uygulayacaksa bunu çağrılır. Çağrılmasa, zaman uyumlu arabirimin yöntemlerini çağrılır. Hem zaman uyumsuz hem de zaman uyumlu arabirimler bir sınıfta uygulanırsa, yalnızca zaman uyumsuz yöntem çağrılır. Gibi soyut sınıflar kullanırken yalnızca zaman uyumlu yöntemleri veya her filtre türü için ActionFilterAttribute zaman uyumsuz yöntemi geçersiz kılın.

Yerleşik filtre öznitelikleri

ASP.NET Core, alt sınıflandırılan ve özelleştirebileceğiniz yerleşik öznitelik tabanlı filtreler içerir. Örneğin, aşağıdaki sonuç filtresi yanıta bir üst bilgi ekler:

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 });
        base.OnResultExecuting(context);
    }
}

Öznitelikler, filtrelerin önceki örnekte gösterildiği gibi bağımsız değişkenleri kabul etmelerine olanak sağlar. değerini AddHeaderAttribute bir denetleyiciye veya eylem yöntemine uygulayarak HTTP üst bilgisi adını ve değerini belirtin:

[AddHeader("Author", "Joe Smith")]
public class SampleController : Controller
{
    public IActionResult Index()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }

    [ShortCircuitingResourceFilter]
    public IActionResult SomeResource()
    {
        return Content("Successful access to resource - header is set.");
    }

Filtre arabirimlerinin birkaçı, özel uygulamalar için temel sınıflar olarak kullanılan ilgili özniteliklere sahiptir.

Filtre öznitelikleri:

Kapsamları ve yürütme sıralamalarını filtreleme

İşlem hattına üç kapsamdan biri ile bir filtre eklenebilir:

  • Eylemde öznitelik kullanma.
  • Denetleyicide öznitelik kullanma.
  • Aşağıdaki kodda gösterildiği gibi tüm denetleyiciler ve eylemler için genel olarak:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(new AddHeaderAttribute("GlobalAddHeader",
            "Result filter added to MvcOptions.Filters"));         // An instance
        options.Filters.Add(typeof(MySampleActionFilter));         // By type
        options.Filters.Add(new SampleGlobalActionFilter());       // An instance
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Yukarıdaki kod, MvcOptions.Filters koleksiyonunu kullanarak genel olarak üç filtre ekler.

Varsayılan yürütme sırası

Aynı türde birden çok filtre olduğunda kapsam, filtre yürütmenin varsayılan sıralarını belirler. Genel filtreler sınıf filtrelerini çevreler. Sınıf filtreleri yöntem filtrelerini çevreler.

Filtre iç içe yerleştirmenin bir sonucu olarak, filtrelerden sonra gelen kodu, önceki kodun ters sırasına göre çalışır. Filtre sırası:

  • Genel filtrelerin önceki kodu.
    • Denetleyici filtrelerinin önceki kodu.
      • Eylem yöntemi filtresinin önceki kodu.
      • Eylem sonrası kodu yöntem filtreleri.
    • Denetleyici filtrelerinin son kodu.
  • Genel filtrelerin sonrası kodu.

Zaman uyumlu eylem filtreleri için filtre yöntemlerinin çağrılma sırası gösteren aşağıdaki örnek.

Sequence Filtre kapsamı Filter yöntemi
1 Genel OnActionExecuting
2 Denetleyici OnActionExecuting
3 Yöntem OnActionExecuting
4 Yöntem OnActionExecuted
5 Denetleyici OnActionExecuted
6 Genel OnActionExecuted

Bu dizi şunları gösterir:

  • Yöntem filtresi, denetleyici filtresi içinde iç içe geçmiştir.
  • Denetleyici filtresi genel filtre içinde iç içe geçmiştir.

Denetleyici ve Razor Sayfa düzeyi filtreleri

Temel sınıftan devralan her Controller denetleyici , ve yöntemlerini Controller.OnActionExecuting Controller.OnActionExecutionAsync Controller.OnActionExecuted OnActionExecuted içerir. Bu yöntemler:

  • Belirli bir eylem için çalıştıran filtreleri sarmalar.
  • OnActionExecuting eylem filtrelerinin herhangi biri öncesinde çağrılır.
  • OnActionExecuted tüm eylem filtrelerinin ardından çağrılır.
  • OnActionExecutionAsync eylem filtrelerinin herhangi biri öncesinde çağrılır. Eylem yönteminin ardından next çalıştır çalıştır çalıştırktan sonra filtrede yer alan kod.

Örneğin, indirme örneğinde başlangıçta MySampleActionFilter genel olarak uygulanır.

: TestController

  • Eyleme SampleActionFilterAttribute [SampleActionFilter] () FilterTest2 uygular.
  • ve geçersiz OnActionExecuting OnActionExecuted kılmaları.
public class TestController : Controller
{
    [SampleActionFilter]
    public IActionResult FilterTest2()
    {
        return Content($"From FilterTest2");
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
        base.OnActionExecuting(context);
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
        base.OnActionExecuted(context);
    }
}

'a giderek https://localhost:5001/Test/FilterTest2 aşağıdaki kodu çalıştırır:

  • TestController.OnActionExecuting
    • MySampleActionFilter.OnActionExecuting
      • SampleActionFilterAttribute.OnActionExecuting
        • TestController.FilterTest2
      • SampleActionFilterAttribute.OnActionExecuted
    • MySampleActionFilter.OnActionExecuted
  • TestController.OnActionExecuted

Sayfalar Razor için bkz. Razor Filtre yöntemlerini geçersiz karak Sayfa filtrelerini uygulama.

Varsayılan sırayı geçersiz kılma

Varsayılan yürütme sırası uygulanarak geçersiz IOrderedFilter kılınabilir. IOrderedFilter yürütme sırası Order belirlemek için kapsamdan öncelikli olan özelliğini ortaya çıkarır. Daha düşük değere sahip Order bir filtre:

  • daha yüksek değerine sahip bir filtreden önceki kodunu Order çalıştırır.
  • Daha yüksek bir değere sahip bir filtreden sonra gelen kodunu Order çalıştırır.

özelliği Order bir oluşturucu parametresiyle belirtebilirsiniz:

[MyFilter(Name = "Controller Level Attribute", Order=1)]

Önceki örnekte gösterilen 3 eylem filtrelerini göz önünde bulundurabilirsiniz. Denetleyicinin Order ve genel filtrelerin özelliği sırasıyla 1 ve 2 olarak ayarlanırsa yürütme sırası tersine çevrilir.

Sequence Filtre kapsamı Order özelliði Filter yöntemi
1 Yöntem 0 OnActionExecuting
2 Denetleyici 1 OnActionExecuting
3 Genel 2 OnActionExecuting
4 Genel 2 OnActionExecuted
5 Denetleyici 1 OnActionExecuted
6 Yöntem 0 OnActionExecuted

OrderÖzelliği filtrelerin çalıştırılacağı sıra belirlenirken kapsamı geçersiz kılar. Filtreler sırasıyla sıraya göre sıralanır, ardından kapsam bölmek için kullanılır. Yerleşik filtrelerin hepsi uygular IOrderedFilter ve varsayılan Order değeri 0 olarak ayarlar. Yerleşik filtreler için kapsam, Order sıfır olmayan bir değere ayarlanmadığı takdirde sıralamayı belirler.

İptal ve kısa devre dışı

Filtre işlem hattı, Result ResourceExecutingContext filtre yöntemine sunulan parametrede özelliği ayarlanarak kısa devre yapılabilir. Örneğin, aşağıdaki kaynak filtresi, ardışık düzenin geri kalanının yürütülmesini engeller:

public class ShortCircuitingResourceFilterAttribute : Attribute, IResourceFilter
{
    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        context.Result = new ContentResult()
        {
            Content = "Resource unavailable - header not set."
        };
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
    }
}

Aşağıdaki kodda, ShortCircuitingResourceFilter ve AddHeader filtresi SomeResource Action metodunu hedefleyin. ShortCircuitingResourceFilterŞunları yapın:

  • İlk olarak bir kaynak filtresi olduğundan ve bir AddHeader eylem filtresiyle çalışır.
  • Kısa süreli işlem hattının geri kalanı.

Bu nedenle, AddHeader filtre eylem için hiçbir şekilde çalışmayacaktır SomeResource . Bu davranış, her iki filtre de eylem yöntemi düzeyinde uygulanırsa, ilk olarak çalıştırıldığında aynı olur ShortCircuitingResourceFilter . İlk olarak, ShortCircuitingResourceFilter filtre türü veya açıkça özelliğin kullanımı kullanılarak çalışır Order .

[AddHeader("Author", "Joe Smith")]
public class SampleController : Controller
{
    public IActionResult Index()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }

    [ShortCircuitingResourceFilter]
    public IActionResult SomeResource()
    {
        return Content("Successful access to resource - header is set.");
    }

Bağımlılık ekleme

Filtreler türe veya örneğe göre eklenebilir. Bir örnek eklenirse, bu örnek her istek için kullanılır. Bir tür eklenirse, türü etkinleştirilmiş olur. Tür etkinleştirilmiş bir filtre şu anlama gelir:

  • Her istek için bir örnek oluşturulur.
  • Herhangi bir Oluşturucu bağımlılığı bağımlılık ekleme (dı) tarafından doldurulur.

Öznitelik olarak uygulanan ve doğrudan denetleyici sınıflarına veya eylem yöntemlerine eklenen filtreler bağımlılık ekleme (dı) tarafından sağlanmış Oluşturucu bağımlılıklarına sahip olamaz. Oluşturucu bağımlılıkları şu nedenle şu nedenle sağlanamaz:

  • Özniteliklerin, uygulandıkları yerlerde, Oluşturucu parametreleri sağlanmalıdır.
  • Bu, özniteliklerin nasıl çalıştığı konusunda bir kısıtlamadır.

Aşağıdaki filtreler, dı tarafından belirtilen Oluşturucu bağımlılıklarını destekler:

Önceki filtreler bir denetleyiciye veya eylem yöntemine uygulanabilir:

Günlükçüler, DI 'den alınabilir. Ancak, yalnızca günlüğe kaydetme amacıyla filtre oluşturmaktan ve kullanmaktan kaçının. Yerleşik çerçeve günlüğü genellikle günlüğe kaydetme için gerekenleri sağlar. Filtrelere günlük eklendi:

  • , İş etki alanı kaygılarını veya filtreye özgü davranışları odaklamalıdır.
  • Eylemleri veya diğer çerçeve olaylarını günlüğe içermemelidir . Yerleşik filtreler günlük eylemleri ve çerçeve olayları.

ServiceFilterAttribute

Hizmet filtresi uygulama türleri ' de kaydedilir ConfigureServices . Bir ServiceFilterAttribute filtrenin bir örneğini alır.

Aşağıdaki kod şunu gösterir AddHeaderResultServiceFilter :

public class AddHeaderResultServiceFilter : IResultFilter
{
    private ILogger _logger;
    public AddHeaderResultServiceFilter(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<AddHeaderResultServiceFilter>();
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        var headerName = "OnResultExecuting";
        context.HttpContext.Response.Headers.Add(
            headerName, new string[] { "ResultExecutingSuccessfully" });
        _logger.LogInformation("Header added: {HeaderName}", headerName);
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // Can't add to headers here because response has started.
    }
}

Aşağıdaki kodda, AddHeaderResultServiceFilter dı kapsayıcısına eklenmiştir:

public void ConfigureServices(IServiceCollection services)
{
    // Add service filters.
    services.AddScoped<AddHeaderResultServiceFilter>();
    services.AddScoped<SampleActionFilterAttribute>();

    services.AddMvc(options =>
    {
        options.Filters.Add(new AddHeaderAttribute("GlobalAddHeader",
            "Result filter added to MvcOptions.Filters"));         // An instance
        options.Filters.Add(typeof(MySampleActionFilter));         // By type
        options.Filters.Add(new SampleGlobalActionFilter());       // An instance
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Aşağıdaki kodda, ServiceFilter özniteliği, bir filtrenin bir ÖRNEĞINI AddHeaderResultServiceFilter dı:

[ServiceFilter(typeof(AddHeaderResultServiceFilter))]
public IActionResult Index()
{
    return View();
}

Kullanırken ServiceFilterAttribute , ayarı ServiceFilterAttribute.IsReusable :

  • Filtre örneğinin, içinde oluşturulduğu istek kapsamının dışında yeniden kullanılabilir olabileceğini gösteren bir ipucu sağlar. ASP.NET Core çalışma zamanı garanti etmez:

    • Filtrenin tek bir örneğinin oluşturulması gerekir.
    • Filtre, sonraki bir noktada dı kapsayıcısından yeniden istenmeyecek.
  • Tek bir yaşam süresine sahip hizmetlere bağımlı olan bir filtreyle kullanılmamalıdır.

ServiceFilterAttribute uygular IFilterFactory . IFilterFactoryCreateInstanceörnek oluşturma yöntemini gösterir IFilterMetadata . CreateInstance belirtilen türü DI 'dan yükler.

TypeFilterAttribute

TypeFilterAttribute benzerdir ServiceFilterAttribute , ancak türü doğrudan dı kapsayıcısından çözümlenmez. Kullanarak türü başlatır Microsoft.Extensions.DependencyInjection.ObjectFactory .

TypeFilterAttributeTürler doğrudan dı kapsayıcısından çözümlenmediğinden:

  • ' İ kullanılarak başvurulan türlerin, TypeFilterAttribute dı kapsayıcısına kayıtlı olması gerekmez. Bunların bağımlılıkları, dı kapsayıcısı tarafından yerine getirilir.
  • TypeFilterAttribute isteğe bağlı olarak tür için Oluşturucu bağımsız değişkenlerini kabul edebilir.

Kullanırken TypeFilterAttribute , ayarı TypeFilterAttribute.IsReusable :

  • Filtre örneğinin, içinde oluşturulduğu istek kapsamının dışında yeniden kullanılabilir olabileceği ipucu sağlar. ASP.NET Core çalışma zamanı, filtrenin tek bir örneğinin oluşturulacağı garantisi vermez.

  • Tek bir yaşam süresine sahip hizmetlere bağımlı olan bir filtreyle kullanılmamalıdır.

Aşağıdaki örnek kullanarak bir türe bağımsız değişkenlerin nasıl geçirileceğini göstermektedir TypeFilterAttribute :

[TypeFilter(typeof(LogConstantFilter),
    Arguments = new object[] { "Method 'Hi' called" })]
public IActionResult Hi(string name)
{
    return Content($"Hi {name}");
}
public class LogConstantFilter : IActionFilter
{
    private readonly string _value;
    private readonly ILogger<LogConstantFilter> _logger;

    public LogConstantFilter(string value, ILogger<LogConstantFilter> logger)
    {
        _logger = logger;
        _value = value;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        _logger.LogInformation(_value);
    }

    public void OnActionExecuted(ActionExecutedContext context)
    { }
}

Yetkilendirme filtreleri

Yetkilendirme filtreleri:

  • , Filtre ardışık düzeninde ilk filtrelerin çalıştırılmasıyla sonuçlanır.
  • Eylem yöntemlerine erişimi denetleyin.
  • Bir Before yöntemi, ancak After yönteminden hiçbiri.

Özel Yetkilendirme filtreleri özel bir yetkilendirme çerçevesi gerektirir. Özel bir filtre yazmak için yetkilendirme ilkelerini yapılandırmayı veya özel bir yetkilendirme ilkesi yazmayı tercih edin. Yerleşik yetkilendirme filtresi:

  • Yetkilendirme sistemini çağırır.
  • İstekleri yetkilendirmez.

Yetkilendirme filtreleri içinde özel durumlar atamayın:

  • Özel durum işlenmeyecektir.
  • Özel durum filtreleri özel durumu işleymeyecektir.

Bir yetkilendirme filtresinde özel durum oluştuğunda bir sınama vermeyi düşünün.

Yetkilendirmehakkında daha fazla bilgi edinin.

Kaynak filtreleri

Kaynak filtreleri:

Kaynak filtreleri, işlem hattının büyük bir çoğunu kısa devre yapmak için kullanışlıdır. Örneğin, bir önbelleğe alma filtresi, önbellek isabeti üzerinde işlem hattının geri kalanını önler.

Kaynak filtresi örnekleri:

Eylem filtreleri

Önemli

Eylem filtreleri Sayfalar için Razor geçerli değildir. Razor Sayfalar ve 'i IPageFilter IAsyncPageFilter destekler. Daha fazla bilgi için bkz. Sayfalar için filtreleme Razor yöntemleri.

Eylem filtreleri:

Aşağıdaki kod bir örnek eylem filtresini gösterir:

public class MySampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
    }
}

ActionExecutingContextaşağıdaki özellikleri sağlar:

  • ActionArguments - Bir eylem yöntemine yapılan girişlerin okunmalarını sağlar.
  • Controller - denetleyici örneğini manipüle etmeye olanak sağlar.
  • Result - eylem Result yönteminin ve sonraki eylem filtrelerinin kısa devre yürütmesini ayarlama.

Eylem yönteminde özel durum atma:

  • Sonraki filtrelerin çalıştırmasını önler.
  • ayarının Result aksine, başarılı bir sonuç yerine hata olarak kabul edilir.

ActionExecutedContextve Controller artı olarak aşağıdaki Result özellikleri sağlar:

  • Canceled - Eylem yürütmenin başka bir filtre tarafından kısa devresi varsa true olur.

  • Exception - Eylem veya daha önce çalıştırılan eylem filtresi bir özel durum oluşturdu ise null değildir. Bu özelliği null olarak ayarlama:

    • Özel durumu etkili bir şekilde işleme.
    • Result , eylem yönteminden döndürüldü gibi yürütülür.

için IAsyncActionFilter çağrısı: ActionExecutionDelegate

  • Sonraki tüm eylem filtrelerini ve eylem yöntemini yürütür.
  • ActionExecutedContext döndürür.

Kısa devre için bir Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext.Result sonuç örneğine atayın ve çağrıyın next (). ActionExecutionDelegate

Çerçeve, alt ActionFilterAttribute sınıflandırılan bir soyutlama sağlar.

Eylem OnActionExecuting filtresi şunları yapmak için kullanılabilir:

  • Model durumunu doğrulama.
  • Durum geçersizse bir hata döndürür.
public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }

yöntemi OnActionExecuted eylem yöntemi sonrasında çalışır:

  • Ayrıca özelliği aracılığıyla eylemin sonuçlarını görebilir ve iş Result görebilir.

  • Canceled , eylem yürütmenin başka bir filtre tarafından kısa devresi varsa true olarak ayarlanır.

  • Exception , eylem veya sonraki bir eylem filtresi bir özel durum oluşturdu ise null olmayan bir değere ayarlanır. Null Exception olarak ayarlanır:

    • Bir özel durumu etkili bir şekilde işleme.
    • ActionExecutedContext.Result , eylem yönteminden normal olarak döndürüldü gibi yürütülür.
public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }


    public override void OnActionExecuted(ActionExecutedContext context)
    {
        var result = context.Result;
        // Do something with Result.
        if (context.Canceled == true)
        {
            // Action execution was short-circuited by another filter.
        }

        if(context.Exception != null)
        {
            // Exception thrown by action or action filter.
            // Set to null to handle the exception.
            context.Exception = null;
        }
        base.OnActionExecuted(context);
    }
}

Özel durum filtreleri

Özel durum filtreleri:

Aşağıdaki örnek özel durum filtresi, uygulama geliştirme aşamasındayken oluşan özel durumlar hakkında ayrıntıları görüntülemek için özel bir hata görünümü kullanır:

public class CustomExceptionFilter : IExceptionFilter
{
    private readonly IHostingEnvironment _hostingEnvironment;
    private readonly IModelMetadataProvider _modelMetadataProvider;

    public CustomExceptionFilter(
        IHostingEnvironment hostingEnvironment,
        IModelMetadataProvider modelMetadataProvider)
    {
        _hostingEnvironment = hostingEnvironment;
        _modelMetadataProvider = modelMetadataProvider;
    }

    public void OnException(ExceptionContext context)
    {
        if (!_hostingEnvironment.IsDevelopment())
        {
            return;
        }
        var result = new ViewResult {ViewName = "CustomError"};
        result.ViewData = new ViewDataDictionary(_modelMetadataProvider,
                                                    context.ModelState);
        result.ViewData.Add("Exception", context.Exception);
        // TODO: Pass additional detailed data via ViewData
        context.Result = result;
    }
}

Özel durum filtreleri:

  • Olaylardan önce ve sonraya sahip değil.
  • veya OnException OnExceptionAsync uygulama.
  • Sayfa veya denetleyici oluşturma, model bağlama, eylem filtreleri Razor veya eylem yöntemlerinde oluşanişlanmamış özel durumları işleyebilirsiniz.
  • Kaynak filtrelerde, sonuç filtrelerde veya MVC sonuç yürütmesinde oluşan özel durumları yakalayın.

Bir özel durumu işlemek için özelliğini ExceptionHandled olarak ayarlayın veya yanıt true yazın. Bu, özel durumun yayılmasını durdurur. Özel durum filtresi bir özel durumu "başarılı" durumuna dönüştüre değildir. Bunu yalnızca bir eylem filtresi yapar.

Özel durum filtreleri:

  • Eylemler içinde oluşan özel durumları yakalama için iyidir.
  • Hata işleme ara yazılımı kadar esnek değildir.

Özel durum işleme için ara yazılımı tercih edin. Yalnızca hata işlemenin hangi eylem yönteminin çağrıldıklarına göre farklılık gösterirken özel durum filtrelerini kullanın. Örneğin, bir uygulamanın hem API uç noktaları hem de görünümler/HTML için eylem yöntemleri olabilir. API uç noktaları hata bilgilerini JSON olarak, görünüm tabanlı eylemler ise HTML olarak bir hata sayfası döndürür.

Sonuç filtreleri

Sonuç filtreleri:

IResultFilter ve IAsyncResultFilter

Aşağıdaki kod, HTTP üst bilgisi ekleyen bir sonuç filtresini gösterir:

public class AddHeaderResultServiceFilter : IResultFilter
{
    private ILogger _logger;
    public AddHeaderResultServiceFilter(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<AddHeaderResultServiceFilter>();
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        var headerName = "OnResultExecuting";
        context.HttpContext.Response.Headers.Add(
            headerName, new string[] { "ResultExecutingSuccessfully" });
        _logger.LogInformation("Header added: {HeaderName}", headerName);
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // Can't add to headers here because response has started.
    }
}

Yürütülen sonuç türü, eyleme bağlıdır. Görünüm döndüren bir eylem, yürütülen işleminin bir parçası olarak tüm razor ViewResult işlemlerini içerir. API yöntemi, sonucun yürütülmesinin bir parçası olarak bazı serileştirmeler gerçekleştirebilirsiniz. Eylem sonuçları hakkında daha fazla bilgi.

Sonuç filtreleri yalnızca bir eylem veya eylem filtresi eylem sonucu ürettiği zaman yürütülür. Sonuç filtreleri şu zaman yürütülmez:

  • Yetkilendirme filtresi veya kaynak filtresi işlem hattını kısa devreler.
  • Özel durum filtresi, bir eylem sonucu üreterek bir özel durumu işler.

yöntemi, Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuting olarak ayararak eylem sonucu ve sonraki sonuç filtrelerinin kısa devre yürütmesini devre dışı Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext.Cancel true bırakır. Boş yanıt oluşturmamak için kısa bağlantı hattı kullanılırken yanıt nesnesine yazın. içinde bir özel durum IResultFilter.OnResultExecuting atarak:

  • Eylem sonucu ve sonraki filtrelerin yürütülmesini engelleme.
  • Başarılı bir sonuç yerine hata olarak kabul edilir.

Yöntem Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuted çalıştır geldiğinde yanıt büyük olasılıkla istemciye zaten gönderilmiştir. Yanıt zaten istemciye gönderilmişse, daha fazla değiştirilemez.

ResultExecutedContext.Canceled , eylem sonucu true yürütmenin başka bir filtre tarafından kısa devresi varsa olarak ayarlanır.

ResultExecutedContext.Exception eylem sonucu veya sonraki bir sonuç filtresi bir özel durum oluşturdu ise null olmayan bir değere ayarlanır. null olarak ayarlanırsa bir özel durum etkili bir şekilde işlenebilir ve özel durumun işlem hattının sonraki ASP.NET Core tarafından Exception yeniden atması önlenebilir. Sonuç filtresinde bir özel durum işlenmişken yanıta veri yazmanın güvenilir bir yolu yoktur. Bir eylem sonucu özel durum ortaya çıkan üst bilgiler istemciye boşaltıldısa, hata kodu göndermek için güvenilir bir mekanizma yoktur.

için, IAsyncResultFilter üzerinde await next çağrısı, sonraki tüm sonuç ResultExecutionDelegate filtrelerini ve eylem sonucu yürütür. Kısa devre için olarak ResultExecutingContext.Cancel ayarlayın true ve çağrısına gerek ResultExecutionDelegate yok:

public class MyAsyncResponseFilter : IAsyncResultFilter
{
    public async Task OnResultExecutionAsync(ResultExecutingContext context,
                                             ResultExecutionDelegate next)
    {
        if (!(context.Result is EmptyResult))
        {
            await next();
        }
        else
        {
            context.Cancel = true;
        }

    }
}

Çerçeve, alt ResultFilterAttribute sınıflandırılan bir soyutlama sağlar. Daha önce gösterilen AddHeaderAttribute sınıfı bir sonuç filtresi özniteliği örneğidir.

IAlwaysRunResultFilter ve IAsyncAlwaysRunResultFilter

IAlwaysRunResultFilterVe IAsyncAlwaysRunResultFilter arabirimleri, IResultFilter tüm eylem sonuçları için çalışan bir uygulama bildirir. Bu, tarafından oluşturulan eylem sonuçlarını içerir:

  • Kısa devre olan Yetkilendirme filtreleri ve kaynak filtreleri.
  • Özel durum filtreleri.

Örneğin, aşağıdaki filtre her zaman çalışır ve ObjectResult içerik anlaşması başarısız olduğunda 422 olmayan bir varlık durum kodu ile bir eylem sonucu () ayarlar:

public class UnprocessableResultFilter : Attribute, IAlwaysRunResultFilter
{
    public void OnResultExecuting(ResultExecutingContext context)
    {
        if (context.Result is StatusCodeResult statusCodeResult &&
            statusCodeResult.StatusCode == (int) HttpStatusCode.UnsupportedMediaType)
        {
            context.Result = new ObjectResult("Can't process this!")
            {
                StatusCode = (int) HttpStatusCode.UnsupportedMediaType,
            };
        }
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
    }
}

IFilterFactory

IFilterFactory uygular IFilterMetadata . Bu nedenle, bir IFilterFactory örnek, IFilterMetadata filtre ardışık düzeninde herhangi bir yerde örnek olarak kullanılabilir. Çalışma zamanı filtreyi çağırmayı hazırlarken, bir öğesine dönüştürmeyi dener IFilterFactory . Atama başarılı olursa, CreateInstance çağrılan örneği oluşturmak için yöntemi çağırılır IFilterMetadata . Bu, tam filtre işlem hattının uygulama başladığında açıkça ayarlanması gerektiğinden esnek bir tasarım sağlar.

IFilterFactory , filtre oluşturmaya yönelik başka bir yaklaşım olarak özel öznitelik uygulamaları kullanılarak uygulanabilir:

public class AddHeaderWithFactoryAttribute : Attribute, IFilterFactory
{
    // Implement IFilterFactory
    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        return new InternalAddHeaderFilter();
    }

    private class InternalAddHeaderFilter : IResultFilter
    {
        public void OnResultExecuting(ResultExecutingContext context)
        {
            context.HttpContext.Response.Headers.Add(
                "Internal", new string[] { "My header" });
        }

        public void OnResultExecuted(ResultExecutedContext context)
        {
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Önceki kod, indirme örneğiçalıştırılarak test edilebilir:

  • F12 geliştirici araçlarını çağırın.
  • https://localhost:5001/Sample/HeaderWithFactory sayfasına gidin.

F12 geliştirici araçları, örnek kod tarafından eklenen aşağıdaki yanıt üstbilgilerini görüntüler:

  • Yazar:Joe Smith
  • globaladdheader:Result filter added to MvcOptions.Filters
  • iç:My header

Yukarıdaki kod, iç: My header yanıt üst bilgisini oluşturur.

Öznitelik üzerinde IFilterFactory uygulandı

Uygulayan filtreler IFilterFactory Şu filtreler için yararlıdır:

  • Parametre geçirme gerekmez.
  • DI tarafından doldurulması gereken Oluşturucu bağımlılıkları vardır.

TypeFilterAttribute uygular IFilterFactory . IFilterFactoryCreateInstanceörnek oluşturma yöntemini gösterir IFilterMetadata . CreateInstance belirtilen türü hizmetler kapsayıcısından (dı) yükler.

public class SampleActionFilterAttribute : TypeFilterAttribute
{
    public SampleActionFilterAttribute():base(typeof(SampleActionFilterImpl))
    {
    }

    private class SampleActionFilterImpl : IActionFilter
    {
        private readonly ILogger _logger;
        public SampleActionFilterImpl(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<SampleActionFilterAttribute>();
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            _logger.LogInformation("Business action starting...");
            // perform some business logic work

        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            // perform some business logic work
            _logger.LogInformation("Business action completed.");
        }
    }
}

Aşağıdaki kod, uygulamak için üç yaklaşımda gösterilmiştir [SampleActionFilter] :

[SampleActionFilter]
public IActionResult FilterTest()
{
    return Content($"From FilterTest");
}

[TypeFilter(typeof(SampleActionFilterAttribute))]
public IActionResult TypeFilterTest()
{
    return Content($"From ServiceFilterTest");
}

// ServiceFilter must be registered in ConfigureServices or
// System.InvalidOperationException: No service for type '<filter>' has been registered.
// Is thrown.
[ServiceFilter(typeof(SampleActionFilterAttribute))]
public IActionResult ServiceFilterTest()
{
    return Content($"From ServiceFilterTest");
}

Yukarıdaki kodda, yöntemi ile dekorasyon, [SampleActionFilter] uygulamak için tercih edilen yaklaşımdır SampleActionFilter .

Filtre ardışık düzeninde ara yazılım kullanma

Kaynak filtreleri, işlem hattında daha sonra gelen her şeyin yürütülmesini çevreleyecek olan Ara yazılım gibi çalışır. ancak filtreler, ASP.NET Core çalışma zamanının bir parçası olan ara yazılımlar dışında farklılık gösterir, bu da ASP.NET Core bağlamına ve yapılarına erişime sahip oldukları anlamına gelir.

Ara yazılımı bir filtre olarak kullanmak için, Configure filtre ardışık düzenine eklenecek olan ara yazılımı belirten bir yöntemi olan bir tür oluşturun. Aşağıdaki örnek, bir istek için geçerli kültürü oluşturmak üzere yerelleştirme ara yazılımını kullanır:

public class LocalizationPipeline
{
    public void Configure(IApplicationBuilder applicationBuilder)
    {
        var supportedCultures = new[]
        {
            new CultureInfo("en-US"),
            new CultureInfo("fr")
        };

        var options = new RequestLocalizationOptions
        {

            DefaultRequestCulture = new RequestCulture(culture: "en-US", 
                                                     uiCulture: "en-US"),
            SupportedCultures = supportedCultures,
            SupportedUICultures = supportedCultures
        };
        options.RequestCultureProviders = new[] 
            { new RouteDataRequestCultureProvider() { Options = options } };

        applicationBuilder.UseRequestLocalization(options);
    }
}

MiddlewareFilterAttributeAra yazılımını çalıştırmak için kullanın:

[Route("{culture}/[controller]/[action]")]
[MiddlewareFilter(typeof(LocalizationPipeline))]
public IActionResult CultureFromRouteData()
{
    return Content($"CurrentCulture:{CultureInfo.CurrentCulture.Name},"
        + $"CurrentUICulture:{CultureInfo.CurrentUICulture.Name}");
}

Ara yazılım filtreleri, filtre işlem hattının aynı aşamasında, model bağlamadan önce ve işlem hattının geri kalanı ile kaynak filtreleri olarak çalışır.

İş parçacığı güvenliği

Bir filtrenin bir örneğini içine geçirirken, Add Type filtre tek olur ve iş parçacığı açısından güvenli değildir .

Sonraki eylemler