ASP.NET Core tarafında farkında olunduğu zaman değişik ihtiyaçlar için çözüm olabilecek ama çok fazla gündeme gelmeyen çeşitli API’lar mevcut. Bunlardan biri de IHostingStartup ara yüzü. Geliştiriciler için SDK/Framework/eklenti tarzı araçlar geliştiriyorsanız ya da uygulama başlarken bazı kontroller yapmanız gerekiyorsa faydalanabileceğiniz bir ara yüz. Hızlıca ve kısaca ne olduğunu, neden tercih edilebilir bahsetmeye çalışacağım.
Ama önce bir hatırlatma…
Bildiğiniz gibi ASP.NET Core uygulamaları “host” kavramı ile çalışır. Bu “host” yaklaşımı uygulamanın başlamasını ve yaşam döngüsünün yönetilebilmesini sağlar. ASP.NET Core uygulamalarındaki standart proje şablonlarındaki Program.cs içeriğinden hatırlayabiliriz.
Bir host(IWebHostBuilder) yaratıyoruz, bunu konfigürasyon ile ayarlıyor, gerekli servisleri ekliyor ve uygulamanın yaşam döngüsünü oluşturuyoruz.
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureServices(services => { services.AddRazorPages(); }) .Configure(app=> { var env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); }); }); }
Ama tabi biraz da düzenli olması adına, ek bir Startup.cs içeriği ile bu yapıyı farklı bir sınıf içerisinde, UseStartup() metodu ile kullanabiliyoruz, -ki zaten standart proje şablonlarından hep bu şekilde geldiği için bu yönteme daha aşinayız. Ama genel ASP.NET Core’daki yapıyı bilmek önemli diye düşünüyorum.
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); }
Bu küçük hatırlatma ile aslında paylaşmak istediğim konuya giriş için kapıyı açmış oldum. Bütün bu işlemlerden önce uygulamadan ayrı bir şekilde bazı işlemleri ASP.NET Core’da nasıl yapabiliyoruz bir bakalım.
IHostingStartup
IHostingStartup arayüzü, ASP.NET Core’da IWebHostBuilder ile “host” oluşturulurken, öncesinde bazı işlemleri yapabilmek için tercih edebileceğimiz bir yöntem. Bu özelliğin bir güzel yanı, mevcut bir ASP.NET Core uygulamasından bağımsız ayrı bir *.dll üzerinden bazı işlemleri yapabilmek; belli konfigürasyonları uygulamaya eklemek ya da belli işlemleri gerçekleştirmek gibi.
Biraz daha net anlaşılması için şöyle örnekler verebilirim; lisans kontrolü, uygulamanın aktivasyonu, uygulama çalışmadan önce bazı ayarların sistem seviyesinde yapılması ve kontrolü(belli dizinlerin yaratılması, belli dosyaların yedeklenmesi…gibi) ya da uygulamanın sağlıklı çalışması için bazı taşıma-dönüşüm işlemlerinin önceden yapılması…
“Eee zaten yapabiliriz, yapılabilir böyle şeyler” diyenler olacaktır. Tabi ki bir şekilde bu tarz gereksinimleri gerçekleştirebiliriz ama neden bunları SDK’nın sağladığı yaklaşımlar ile daha kolay ve .NET için en uygun şekilde yapmayalım.
Yavaştan kod tarafına geçelim ki biraz daha netleşmeye başlasın. Visual Studio’nun standart proje şablonlarından ASP.NET Core Web App(StartupDemos) ve bir tane de Class Library(HostingStartupExternalLibrary) kullanacağım. Class Library, bizim dışardan uygulamaya dahil edeceğimiz, IHostingStartup ara yüzünden türeteceğimiz yapıyı barındıracak; yazının asıl olay yani. ASP.NET Core Web App ise, sadece örnek amaçlı, dışardan ekleyeceğimiz IHostingStartup‘ı kullanacak uygulama.
HostingStartupExternalLibrary projesine bakalım önce. IHostingStartUp arayüzünden yarattığımız tek bir sınıfımız var. Bu arayüzün sağlamış olduğu Configure(IWebHostBuilder) metodu ile WebHost’umuzu ayarlayabiliyoruz. Ben burada örnek olsun diye; bir Web API*‘sine çağrı yapıp dönen değerleri WebHost’un konfigürasyonunda kullanılması için ayarlıyorum. Çok saçma biliyorum ama başka bileşenler/sistemler ile iletişim de kurup, farklı iş ihtiyaçlarını gerçekleştirebilmek adına örnek olabilir. Mesela yazının başında bahsetmiş olduğum senaryolardan; uygulama çalıştığında bir aktivasyon, bu tarz bir Web API çağrımı ile gerçekleşebilir.
*Burada örnek olması adına bu tarz örnekler ve denemeler için kullanılabilecek ücretsiz basit bir Web API kullandım.
using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Net.Http; [assembly: HostingStartup(typeof(HostingStartupExternalLibrary.SomeExternalHostingStartup))] namespace HostingStartupExternalLibrary { public class SomeExternalHostingStartup : IHostingStartup { public void Configure(IWebHostBuilder builder) { HttpClient client = new(); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Add("User-Agent", "SomeSpecificCustomer"); string boredAPIResult = client.GetStringAsync("https://www.boredapi.com/api/activity").Result; var activity = System.Text.Json.JsonDocument.Parse(boredAPIResult); builder.ConfigureAppConfiguration((host, config) => { var externalSettings = new Dictionary<string, string> { {"EXTERNAL_STARTUP_ACTIVITY", activity.RootElement.GetProperty("activity").GetString()}, {"EXTERNAL_STARTUP_TYPE", activity.RootElement.GetProperty("type").GetString()}, {"EXTERNAL_STARTUP_KEY", activity.RootElement.GetProperty("key").GetString()} }; config.AddInMemoryCollection(externalSettings); }); } } }
Burada dikkat ederseniz, IWebHostBuilder üzerinden konfigürasyonlara belli değerleri ekliyoruz. Bu IHostingStartup arayüzünü uygulamadığımız Web uygulamasında, uygulamadan bağımsız olarak bu konfigürasyon değerlerine ulaşabileceğiz. Birazdan oraya da geleceğiz.