Inti ASP.NET yang valid

Inti ASP.NET yang valid


Khusus untuk pecinta buku dari seri "C ++ dalam 24 jam", saya memutuskan untuk menulis artikel tentang ASP.NET Core.


Jika Anda belum mengembangkan di bawah. NET atau di bawah platform serupa sebelumnya, maka tidak masuk akal untuk memotong Anda. Tetapi jika Anda tertarik untuk mempelajari apa yang IoC, DI, DIP, Interseptors, Middleware, Filter (yaitu, segala sesuatu yang berbeda dari Core dari .NET klasik), maka Anda pasti perlu mengklik "Baca lebih lanjut", karena Anda sedang mengembangkan Tanpa memahami semua ini, itu jelas tidak benar.


IoC, DI, DIP


Jika teater dimulai dengan gantungan, maka ASP.NET Core mulai dengan Injeksi Ketergantungan. Untuk menghadapi DI, Anda perlu memahami apa itu IoC.


Berbicara tentang IoC, orang sering mengingat prinsip Hollywood, "Jangan panggil kami, kami akan menghubungi Anda." Yang berarti "Tidak perlu memanggil kami, kami akan memanggil Anda sendiri."


Sumber yang berbeda memberikan pola yang berbeda di mana IoC dapat diterapkan. Dan kemungkinan besar mereka baik-baik saja dan hanya saling melengkapi. Berikut adalah beberapa pola ini: pabrik, pencari lokasi, metode templat, pengamat, strategi.


Mari kita lihat IoC menggunakan aplikasi konsol sederhana sebagai contoh.


Misalkan kita memiliki dua kelas sederhana yang mengimplementasikan antarmuka dengan satu metode:


class ConsoleLayer : ILayer { public void Write(string text) { Console.WriteLine(text); } } class DebugLayer : ILayer { public void Write(string text) { Debug.WriteLine(text); } } interface ILayer { void Write(string text); } 

Keduanya bergantung pada abstraksi (dalam hal ini, antarmuka bertindak sebagai abstraksi).


Dan katakanlah kita memiliki objek level yang lebih tinggi menggunakan kelas-kelas ini:


  class Logging : ILayer { private ILayer _instance; public Logging(int i) { if (i == 1) { _instance = new ConsoleLayer(); } else { _instance = new DebugLayer(); } } public void Write(string text) { _instance.Write(text); } } 

Bergantung pada parameter konstruktor, variabel _instance diinisialisasi oleh kelas tertentu. Baik dan selanjutnya, saat memanggil Write, output ke konsol atau ke Debug akan selesai. Segalanya tampak cukup baik dan bahkan, tampaknya, sesuai dengan bagian pertama dari prinsip Ketergantungan Inversi


Objek tingkat tinggi tidak tergantung pada objek tingkat bawah. Baik itu dan mereka tergantung pada abstraksi.

Dalam kasus kami, ILayer bertindak sebagai abstraksi.


Tetapi kita juga harus memiliki objek yang levelnya lebih tinggi. Salah satu yang menggunakan kelas Logging


  static void Main(string[] args) { var log = new Logging(1); log.Write("Hello!"); Console.Read(); } 

Dengan menginisialisasi Logging dengan 1, kita mendapatkan kelas Logging sebuah instance dari kelas yang menampilkan data ke konsol. Jika kita menginisialisasi Pencatatan dengan nomor lain, maka log. Menulis akan menampilkan data ke Debug. Segala sesuatu, tampaknya, berfungsi, tetapi itu bekerja dengan buruk. Objek tingkat tinggi kami Utama tergantung pada detail kode objek tingkat bawah - kelas Logging. Jika kita mengubah sesuatu di kelas ini, maka kita perlu mengubah kode kelas Utama. Untuk mencegah hal ini terjadi, kami akan membuat inversi kontrol - Pembalikan Kontrol. Mari kita buat kontrol kelas Utama apa yang terjadi di kelas Logging. Kelas Logging akan menerima, sebagai parameter konstruktor, instance dari kelas yang mengimplementasikan antarmuka ILayer


  class Logging { private ILayer _instance; public Logging(ILayer instance) { _instance = instance; } public void Write(string text) { _instance.Write(text); } } 

Dan sekarang, kelas Utama kita akan terlihat seperti ini:


  static void Main(string[] args) { var log = new Logging(new DebugLayer()); log.Write("Hello!"); Console.Read(); } 

Faktanya, kita menghias objek Logging kita dengan objek yang diperlukan untuk kita.


Sekarang aplikasi kita mematuhi bagian kedua dari prinsip Ketergantungan Inversi:


Abstraksi tidak tergantung pada detail. Detail tergantung pada abstraksi. Yaitu kami tidak tahu detail tentang apa yang terjadi di kelas Penebangan, kami hanya melewati kelas di sana yang mengimplementasikan abstraksi yang diperlukan.

Ada istilah kopling ketat - koneksi ketat. Semakin lemah koneksi antara komponen-komponen dalam aplikasi, semakin baik. Saya ingin mencatat bahwa contoh aplikasi sederhana ini tidak mencapai yang ideal sedikit pun. Mengapa Ya, karena di kelas level tertinggi di Utama, kami dua kali menggunakan pembuatan instance kelas menggunakan yang baru. Dan ada ungkapan mnemonik seperti "Baru adalah petunjuk" - yang berarti semakin sedikit Anda menggunakan yang baru, koneksi komponen yang kurang ketat dalam aplikasi dan semakin baik. Idealnya, kita tidak boleh menggunakan DebugLayer baru, tetapi harus mendapatkan DebugLayer dengan cara lain. Yang mana Misalnya, dari wadah IoC atau menggunakan refleksi dari parameter yang diteruskan ke Utama.


Sekarang kami telah menemukan apa Inversion of Control (IoC) itu dan apa Dependency Inversion (DIP) itu. Masih memahami apa Injeksi Ketergantungan (DI). IoC adalah paradigma desain. Ketergantungan Injeksi adalah sebuah pola. Inilah yang sekarang kita miliki dalam konstruktor kelas Logging. Kami mendapatkan contoh ketergantungan tertentu. Kelas Logging tergantung pada instance kelas yang mengimplementasikan ILayer. Dan contoh ini disuntikkan melalui konstruktor.


Wadah IOC


Kontainer IoC adalah objek yang mengandung banyak dependensi spesifik (dependensi). Ketergantungan dapat disebut layanan - sebagai aturan itu adalah kelas dengan fungsi tertentu. Jika perlu, ketergantungan dari jenis yang diperlukan dapat diperoleh dari wadah. Menyuntikkan ketergantungan ke wadah adalah Menyuntikkan. Ekstrak - Putuskan. Berikut adalah contoh wadah IoC yang ditulis sendiri paling sederhana:


  public static class IoCContainer { private static readonly Dictionary<Type, Type> _registeredObjects = new Dictionary<Type, Type>(); public static dynamic Resolve<TKey>() { return Activator.CreateInstance(_registeredObjects[typeof(TKey)]); } public static void Register<TKey, TConcrete>() where TConcrete : TKey { _registeredObjects[typeof(TKey)] = typeof(TConcrete); } } 

Hanya selusin baris kode, tetapi Anda sudah dapat menggunakannya (bukan untuk produksi, tentu saja, tetapi untuk tujuan pendidikan).


Anda dapat mendaftarkan dependensi (misalnya, ConsoleLayer atau DebugLayer yang kami gunakan dalam contoh sebelumnya) seperti ini:


  IoCContainer.Register<ILayer, ConsoleLayer>(); 

Dan ekstrak dari wadah di tempat yang diperlukan dari program seperti ini:


  ILayer layer = IoCContainer.Resolve<ILayer>(); layer.Write("Hello from IoC!"); 

Dalam wadah nyata, Buang () juga diterapkan, yang memungkinkan Anda untuk menghancurkan sumber daya yang telah menjadi tidak perlu.


By the way, nama wadah IoC tidak persis menyampaikan artinya, karena istilah IoC jauh lebih luas dalam aplikasi. Oleh karena itu, baru-baru ini istilah wadah DI telah semakin sering digunakan (karena injeksi ketergantungan masih diterapkan).


Umur layanan + berbagai metode ekstensi di Root Komposisi


Aplikasi Core ASP.NET berisi file Startup.cs, yang merupakan titik awal aplikasi untuk mengkonfigurasi DI. Mengkonfigurasi DI dalam metode ConfigureServices.


  public void ConfigureServices(IServiceCollection services) { services.AddScoped<ISomeRepository, SomeRepository>(); } 

Kode ini akan menambahkan kelas SomeRepository ke wadah DI, yang mengimplementasikan antarmuka ISomeRepository. Fakta bahwa layanan ditambahkan ke wadah menggunakan AddScoped berarti bahwa instance kelas akan dibuat setiap kali halaman diminta.
Anda dapat menambahkan layanan ke sebuah wadah tanpa menentukan antarmuka.


  services.AddScoped<SomeRepository>(); 

Tetapi metode ini tidak disarankan, karena aplikasi Anda kehilangan fleksibilitasnya dan koneksi yang dekat muncul. Disarankan agar Anda selalu menentukan antarmuka, karena dalam hal ini, kapan saja, Anda dapat mengganti satu implementasi antarmuka dengan lainnya. Dan jika implementasi mendukung prinsip substitusi Liskov, maka dengan mengubah nama kelas implementasi dengan "jentikan tangan" Anda akan mengubah fungsionalitas seluruh aplikasi.


Ada 2 opsi lagi untuk menambahkan layanan - AddSingleton dan AddTransient.
Saat menggunakan AddSingleton, layanan dibuat sekali, dan saat menggunakan aplikasi, panggilan masuk ke instance yang sama. Gunakan metode ini terutama dengan hati-hati, karena kebocoran memori dan masalah multithreading mungkin terjadi.


AddSingleton memiliki sedikit fitur. Ini dapat diinisialisasi baik pada akses pertama ke sana


  services.AddSingleton<IYourService, YourService>(); 

baik segera ketika ditambahkan ke konstruktor


  services.AddSingleton<IYourService>(new YourService(param)); 

Dengan cara kedua, Anda bahkan dapat menambahkan parameter ke konstruktor.
Jika Anda ingin menambahkan parameter ke konstruktor layanan yang ditambahkan tidak hanya menggunakan AddSingleton, tetapi juga menggunakan AddTransient / AddScoped, maka Anda dapat menggunakan ekspresi lambda:


  services.AddTransient<IYourService>(o => new YourService(param)); 

Dan akhirnya, ketika menggunakan AddTransient, sebuah layanan dibuat setiap kali Anda mengaksesnya. Bagus untuk layanan ringan yang tidak menghabiskan memori dan sumber daya.


Jika dengan AddSingleton dan AddScoped semuanya harus lebih atau kurang jelas, maka AddTransient perlu klarifikasi. Dokumentasi resmi memberikan contoh di mana layanan tertentu ditambahkan ke wadah DI baik sebagai parameter pembangun layanan lain dan secara terpisah secara terpisah. Dan jika ditambahkan secara terpisah menggunakan AddTransient, ia membuat instance-nya 2 kali. Saya akan memberikan contoh yang sangat, sangat sederhana. Dalam kehidupan nyata, itu tidak dianjurkan untuk digunakan, karena kelas untuk kesederhanaan tidak mewarisi antarmuka. Katakanlah kita memiliki kelas sederhana:


  public class Operation { public Guid OperationId { get; private set; } public Operation() { OperationId = Guid.NewGuid(); } } 

Dan ada kelas kedua yang berisi yang pertama sebagai layanan dependen dan menerima dependensi ini sebagai parameter konstruktor:


  public class OperationService { public Operation Operation { get; } public OperationService (Operation operation) { Operation = operation; } } 

Sekarang kami menyuntikkan dua layanan:


  services.AddTransient<Operation>(); services.AddScoped<OperationService>(); 

Dan di beberapa controller dalam Action, tambahkan tanda terima dari dependensi kami dan tampilkan nilai-nilai di jendela Debug.


  public IActionResult Index([FromServices] Operation operation, [FromServices] OperationService operationService) { Debug.WriteLine(operation.OperationId); Debug.WriteLine(operationService.Operation.OperationId); return View(); } 

Jadi, sebagai hasilnya, kami mendapatkan 2 nilai Guid yang berbeda. Tetapi jika kita mengganti AddTransient dengan AddScoped, maka sebagai hasilnya kita mendapatkan 2 nilai identik.


Wadah IoC aplikasi Core ASP.NET berisi beberapa layanan secara default. Misalnya, IConfiguration adalah layanan yang dengannya Anda bisa mendapatkan pengaturan aplikasi dari file appsettings.json dan appsettings.Development.json. IHostingEnvironment dan ILoggerFactory yang dengannya Anda bisa mendapatkan konfigurasi saat ini dan kelas pembantu yang memungkinkan logging.


Kelas diambil dari wadah menggunakan konstruksi khas berikut (contoh paling umum):


  private readonly IConfiguration _configuration; public SomePageController(IConfiguration configuration) { _configuration = configuration; } public async Task<IActionResult> Index() { string connectionString = _configuration["connectionString"]; } 

Variabel dengan pengubah akses readonly pribadi dibuat dalam lingkup controller. Ketergantungan diperoleh dari wadah di konstruktor kelas dan ditugaskan ke variabel pribadi. Lebih lanjut, variabel ini dapat digunakan dalam metode atau pengontrol tindakan apa pun.
Terkadang Anda tidak ingin membuat variabel untuk menggunakannya hanya dalam satu Tindakan. Kemudian Anda dapat menggunakan atribut [FromServices]. Contoh:


  public IActionResult About([FromServices] IDateTime dateTime) { ViewData["Message"] = «  " + dateTime.Now; return View(); } 

Itu terlihat aneh, tetapi agar tidak memanggil metode kelas DateTime.Now () dalam kode, kadang-kadang dilakukan sehingga nilai waktu diperoleh dari layanan sebagai parameter. Dengan demikian, menjadi mungkin untuk melewatkan setiap saat sebagai parameter, yang berarti menjadi lebih mudah untuk menulis tes dan, sebagai aturan, menjadi lebih mudah untuk membuat perubahan pada aplikasi.
Ini bukan untuk mengatakan bahwa statis itu jahat. Metode statis lebih cepat. Dan kemungkinan besar statis dapat digunakan di suatu tempat di wadah IoC itu sendiri. Tetapi jika kita menyimpan aplikasi kita dari semua yang statis dan baru, maka kita akan mendapatkan lebih banyak fleksibilitas.


Kontainer DI Pihak Ketiga


Apa yang kami lihat dan apa yang sebenarnya diterapkan oleh ASP.NET Core DI container adalah injeksi konstruktor. Masih ada kesempatan untuk menyuntikkan ketergantungan ke properti menggunakan apa yang disebut injeksi properti, tetapi fitur ini tidak tersedia dalam wadah yang dibangun ke dalam ASP.NET Core. Sebagai contoh, kami mungkin memiliki beberapa kelas yang Anda terapkan sebagai dependensi, dan kelas ini memiliki beberapa jenis properti publik. Sekarang bayangkan bahwa selama atau setelah kita menyuntikkan dependensi, kita perlu mengatur nilai properti. Mari kita kembali ke contoh yang mirip dengan contoh yang baru saja kita periksa.
Jika kita memiliki kelas seperti itu:


  public class Operation { public Guid OperationId { get; set; } public Operation() {} } 

yang bisa kita perkenalkan sebagai kecanduan,


  services.AddTransient<Operation>(); 

kemudian menggunakan wadah standar, kami tidak dapat menetapkan nilai untuk properti.
Jika Anda ingin menggunakan kesempatan ini untuk menetapkan nilai untuk properti OperationId, maka Anda dapat menggunakan beberapa jenis wadah DI pihak ketiga yang mendukung injeksi properti. Omong-omong, injeksi properti tidak sangat dianjurkan. Namun, masih ada Metode Injeksi dan Metode Setter Injeksi, yang mungkin berguna bagi Anda dan yang juga tidak didukung oleh wadah standar.


Wadah pihak ketiga mungkin memiliki fitur lain yang sangat berguna. Misalnya, menggunakan wadah pihak ketiga, Anda hanya bisa menambahkan ketergantungan ke pengontrol yang memiliki kata tertentu dalam namanya. Dan cukup sering digunakan kasing - wadah DI, dioptimalkan untuk kinerja.
Berikut adalah daftar beberapa kontainer DI pihak ketiga yang didukung oleh ASP.NET Core: Autofac, Castle Windsor, LightInject, DryIoC, StructureMap, Unity


Meskipun menggunakan wadah DI standar, Anda tidak dapat menggunakan injeksi properti / metode, tetapi Anda dapat menerapkan layanan dependen sebagai parameter konstruktor dengan menerapkan pola Pabrik sebagai berikut:


  services.AddTransient<IDataService, DataService>((dsvc) => { IOtherService svc = dsvc.GetService<IOtherService>(); return new DataService(svc); }); 

Dalam hal ini, GetService akan mengembalikan nol jika layanan dependen tidak ditemukan. Ada variasi GetRequiredService yang akan melempar pengecualian jika layanan dependen tidak ditemukan.
Proses mendapatkan layanan dependen menggunakan GetService sebenarnya menerapkan pola pencari lokasi Layanan.


Autofac


Mari kita lihat Autofac dengan contoh praktis. Dengan mudah, layanan dari wadah dapat didaftarkan dan diterima, baik dengan cara default maupun menggunakan Autofac.


Instal paket NuGet Autofac.Extensions.DependencyInjection.
Ubah nilai yang dikembalikan oleh metode ConfigureServices dari void ke IServiceProvider. Dan tambahkan properti


  public IContainer ApplicationContainer { get; private set; } 

Setelah itu, menjadi mungkin untuk menambahkan kode seperti berikut ke akhir metode ConfigureServices dari kelas Startup (ini hanya salah satu opsi untuk mendaftar layanan):


  services.AddTransient<ISomeRepository, SomeRepository>(); var builder = new ContainerBuilder(); builder.Populate(services); builder.RegisterType<AnotherRepository>().As<IAnotherRepository>(); this.ApplicationContainer = builder.Build(); return new AutofacServiceProvider(this.ApplicationContainer); 

Sini builder. Populasi (layanan); Menambahkan layanan dari IServiceCollection ke wadah. Yah dan selanjutnya sudah dimungkinkan untuk mendaftar layanan dengan builder.RegisterType. Oh ya Saya hampir lupa. Anda harus mengubah dari membatalkan ke IServiceProvider nilai kembali metode ConfigureServices.


AOP dengan ASP.NET Core - Autofac Interseptor


Berbicara tentang pemrograman berorientasi aspek, mereka menyebutkan istilah lain - keprihatinan lintas sektoral. Kepedulian adalah beberapa informasi yang mempengaruhi kode. Dalam versi Rusia mereka menggunakan kata tanggung jawab. Masalah lintas sektoral adalah tanggung jawab yang memengaruhi tanggung jawab lain. Tapi idealnya, mereka seharusnya tidak saling mempengaruhi, kan? Ketika mereka saling mempengaruhi, menjadi lebih sulit untuk mengubah program. Lebih nyaman ketika kita memiliki semua operasi secara terpisah. Logging, transaksi, caching dan banyak lagi dapat dilakukan dengan menggunakan AOP tanpa mengubah kode dari kelas dan metode itu sendiri.


Di dunia .NET, metode sering digunakan ketika kode AOP disematkan menggunakan prosesor pos ke dalam kode aplikasi yang sudah dikompilasi ( PostSharp ). Atau sebagai alternatif, Anda dapat menggunakan pencegat - ini adalah pengait acara yang dapat ditambahkan ke kode aplikasi. Pencegat ini, sebagai suatu peraturan, menggunakan dekorator yang telah kita periksa untuk pekerjaan mereka.


Mari buat pencegat Anda sendiri. Contoh paling sederhana dan paling umum yang paling mudah direproduksi adalah pencatatan.
Selain paket Autofac.Extensions.DependencyInjection, kami juga akan menginstal paket Autofac.Extras.DynamicProxy
Diinstal? Tambahkan kelas log sederhana yang akan dipanggil saat mengakses layanan tertentu.


  public class Logger : IInterceptor { public void Intercept(IInvocation invocation) { Debug.WriteLine($"Calling {invocation.Method.Name} from Proxy"); invocation.Proceed(); } } 

Tambahkan ke registrasi Autofac kami pendaftaran interseptor:


  builder.Register(i => new Logger()); builder.RegisterType<SomeRepository >() .As<ISomeRepository >() .EnableInterfaceInterceptors() .InterceptedBy(typeof(Logger)); 

Dan sekarang, dengan setiap panggilan ke kelas, metode Intercept dari kelas Logger akan dipanggil.
Dengan demikian, kita dapat menyederhanakan hidup kita dan tidak menulis entri log di awal setiap metode. Kami akan memilikinya secara otomatis. Dan jika diinginkan, akan mudah bagi kita untuk mengubah atau menonaktifkannya untuk seluruh aplikasi.


Kami juga dapat menghapus .InterceptedBy (typeof (Logger)); dan tambahkan intersepsi panggilan hanya untuk layanan aplikasi spesifik menggunakan atribut [Intercept (typeof (Logger))] - Anda harus menentukannya sebelum header kelas.


Middleware


ASP.NET memiliki rantai panggilan kode tertentu yang terjadi pada setiap permintaan. Bahkan sebelum UI / MVC dimuat, tindakan tertentu dilakukan.


Itu, misalnya, jika kita menambahkan di awal metode Konfigurasi kelas Startup.cs kode


  app.Use(async (context, next) => { Debug.WriteLine(context.Request.Path); await next.Invoke(); }); 

lalu kita bisa melihat di konsol debug file apa yang diminta aplikasi kita. Bahkan, kami mendapatkan kemampuan AOP "out of box"
Sebagai contoh yang tidak berguna, tetapi jelas dan informatif tentang penggunaan middleware, saya akan menunjukkan kepada Anda sekarang:


  public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { await context.Response.WriteAsync("Hello!" + Environment.NewLine); await next.Invoke(); }); app.Run(async context => { await context.Response.WriteAsync("Hello again."); }); } 

Dengan setiap permintaan, serangkaian panggilan dimulai. Dari setiap aplikasi. Gunakan, setelah memanggil next.invoke (), transisi ke panggilan berikutnya dilakukan. Dan semuanya berakhir setelah aplikasi. Berjalan berfungsi.
Anda dapat menjalankan beberapa kode hanya ketika mengakses rute tertentu.
Anda dapat melakukan ini menggunakan aplikasi. Peta:


  private static void Goodbye(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Goodbye!"); }); } public void Configure(IApplicationBuilder app) { app.Map("/goodbye", Goodbye); app.Run(async context => { await context.Response.WriteAsync("Hello!"); }); } 

Sekarang, jika Anda hanya pergi ke halaman situs, Anda dapat melihat teks "Halo!", Dan jika Anda menambahkan / Selamat tinggal ke bilah alamat, Anda akan melihat Selamat tinggal.


Selain Penggunaan dan Peta, Anda dapat menggunakan UseWhen atau MapWhen untuk menambahkan kode ke rantai middleware hanya dalam kondisi tertentu tertentu.


Sejauh ini masih ada contoh yang tidak berguna, kan? Ini adalah contoh normal:


  app.Use(async (context, next) => { context.Response.Headers.Add("X-Frame-Options", "DENY"); context.Response.Headers.Add("X-Content-Type-Options", "nosniff"); context.Response.Headers.Add("X-Xss-Protection", "1"); await next(); }); 

Di sini kami menambahkan header ke setiap permintaan untuk membantu melindungi halaman dari serangan peretas.


Atau di sini adalah contoh lokalisasi:


  var supportedCultures = new[] { new CultureInfo("ru"), new CultureInfo("fr") }; app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("ru"), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures }); 

Sekarang jika Anda menambahkan parameter? Culture = fr ke alamat halaman, maka Anda dapat mengganti bahasa aplikasi ke bahasa Prancis (jika lokalisasi ditambahkan ke aplikasi Anda, maka semuanya akan berfungsi)


Filter


Jika rantai middleware mengacu pada proses sebelum MVC, maka filter bekerja bersama dengan MVC.
Diagram skematik berikut menunjukkan cara kerja filter.


Filter


Pertama, filter otorisasi berhasil. Yaitu Anda dapat membuat beberapa jenis filter atau beberapa filter dan memasukkan beberapa jenis kode otorisasi yang akan berfungsi berdasarkan permintaan.


Kemudian mereka memenuhi filter sumber daya. Dengan menggunakan filter ini, Anda dapat, misalnya, mengembalikan beberapa informasi dari cache.


Kemudian terjadi pengikatan data dan filter Tindakan dijalankan. Dengan bantuan mereka, Anda dapat memanipulasi parameter yang dikirimkan ke Aksi dan hasil yang dikembalikan.


Filter pengecualian sebagai petunjuk namanya memungkinkan Anda menambahkan semacam penanganan kesalahan umum untuk aplikasi. Seharusnya cukup nyaman untuk menangani kesalahan di tempat yang sama. Semacam AOP-shny plus.


Filter hasil memungkinkan Anda untuk melakukan beberapa tindakan sebelum mengeksekusi Action controller atau sesudahnya. Mereka sangat mirip dengan filter Tindakan, tetapi dieksekusi hanya jika tidak ada kesalahan. Cocok untuk logika yang terkait dengan View.


. :


  public class YourCustomFilter : Attribute, IAuthorizationFilter { public async void OnAuthorization(AuthorizationFilterContext context) { // -    ,     ,    context.Result = new ContentResult() { Content = "        " }; } } 

DI ( Startup.cs)


  services.AddScoped<YourCustomFilter>(); 

- Action


  [ServiceFilter(typeof(YourCustomFilter))] 

– middleware - action . Configure


  public class MyMiddlewareFilter { public void Configure(IApplicationBuilder applicationBuilder) { applicationBuilder.Use(async (context, next) => { Debug.WriteLine("  middleware!"); await next.Invoke(); }); } } 

Action-


  [MiddlewareFilter(typeof(MyMiddlewareFilter))] 

Source: https://habr.com/ru/post/id437002/


All Articles