Farklı domainler için multi tenant middleware kullanımı

Tenant, saas veya store mantığı ile çalışan bir web uygulamamız var diyelim ve yazılan bütün metotlar için appId yi sorgunun sonuna eklemek gerekiyor.Ama biz bu işlemi otomatik hale getireceğiz.
Url bizim appId’mizi verecektir.
Amacımız :
kod temizliği, güvenlik ve esneklik katacaktır uygulamamıza.

Url’den Gelen Tenant ‘ı cache alıyoruz.

protected override Task<TenantContext<AppTenant>> ResolveAsync(HttpContext context)
        {
            TenantContext<AppTenant> tenantContext = null;
            var hostName = context.Request.Host.Value.ToLower();

            var tenant = _tenantService.GetTenantResultByHostName(hostName);

            var appTenant = new AppTenant()
            {
                Id = tenant.tenant.tenantId,
                Host = tenant.tenant.host,
                Name = tenant.tenant.name,
                RequireSSL = tenant.tenant.RequireSSL,
                LanguageId = tenant.tenant.LanguageId
            };

            if (tenant != null)
            {
                tenantContext = new TenantContext<AppTenant>(appTenant);
            }
            return Task.FromResult(tenantContext);
        }


Örneklerle biraz daha açalım konuyu.

1. adımda appId’yi manuel olarak yazacağım ve bir Get işlemi deneyeceğim.

var userList= _userRepository.Table.where(x=>x.AppId == _appId);

2. adımda ise appId’yi middleware de otomatik eklemiş örneği görelim.

var userList= _userRepository.Table;

Aradaki fark şahane dimi.

Bu senaryoda de her tenant’ın kendi domaini var. Proje ayağa kalkerken ayarlar bir defa yüklenecek.
Önce context classımıı açıp içerisine asembly’den faydalanarak bütün veri tabanı entity classlarına appId ekleyip oluşturduğumuz expression’ı HasQueryFilter ile gönderiyoruz.

 private void AddAllConfigurations(ModelBuilder modelBuilder)
{
	foreach (var entityType in modelBuilder.Model.GetEntityTypes())
	{
		ConfigureGlobalFiltersMethodInfo
			.MakeGenericMethod(entityType.ClrType)
			.Invoke(this, new object[] { modelBuilder });
	}
}


private void ConfigureTenantQueryFilter<TEntity>
                       (ModelBuilder modelBuilder) where TEntity : class
        {
            Expression<Func<TEntity, bool>> expression = null;

            if (typeof(IHaveTenant).IsAssignableFrom(typeof(TEntity)))
            {
                expression = e => ((IHaveTenant)e).TenantId == GetTenantId() 
                  || ((IHaveTenant)e).TenantId == null 
                  || ((IHaveTenant)e).TenantId == 0;
            }

            if (expression != null)
            {
                modelBuilder.Entity<TEntity>().HasQueryFilter(expression);
            }
        }

private static readonly MethodInfo ConfigureGlobalFiltersMethodInfo =
            typeof(EfDbContext).GetMethod(nameof(ConfigureTenantQueryFilter),
                BindingFlags.Instance | BindingFlags.NonPublic);

Artık tenant ayarları tamam. Sorgular sadece bulunduğu domain üzerindeki kaynaklara eişecektir.
Daha detaylı bir tenant makalesi ile görüşmek üzere

1 – Blazor NEDİR ?

Geçmişte JavaScript web projelerinde tekel olmuştu. Sonrasında ise geliştiriciler TypeScrip, Angular vb teknolojilerini çıkardılar ama sonuç olarak kodlarımız dönüp dolaşıp javaScript ile kod yazmaya geçiyordu. Ama WebAssembly bu yaklaşımı değiştirdi.

Neden WebAssembly

JavaScript güçlü bir dil ancak dezavantajları vardı. Bazıları TypeScript tarafından düzeltildi amma ve lakin konumuz single page olduğu için aradaki farkı çok fazla gün yüzüne çıkarmayı düşünmüyorum ?

C# yazılımcıları tarafından React, Angular, Vuejs gibi JavaScript ve TypeScript tabanlı dillere geçiş yapmak ve proje geliştirmek ilk araştırma evreleri ve konuyu anlama Freddy’nin kabusu gibi geliyordu.

Single page sayfalarda artık sadece C# kodlarından faydalanarak web uygulamalar geliştirebiliyoruz. Kod yazma performansı olarak örnek vermek gerekirse projelerimde angular ve vue js sık sık kullanırım blazor un verdiği kod yazma performansını hiç bir platformda yakalamazsınız . Proje geliştirmek inanılmaz hızlı gerçekleşiyor.
Blazor’un En sevdiğim tarafı modelleri eşleştirme gibi bir sorununuz artık kalmıyor. En büyük sıkıntı aslında çözülmüş oluyor bu kısımda. Server ve Client tarafı da aynı modelleri kullandığı için çok daha hızlı geliştirme yapabiliyoruz. Diğer bir güzel yani Blazor geliştiricileri Angular vb. teknolojilerde javascript tabanlı kütüphaneleri eklemek imkansız olabiliyordu ama blazor geliştiricileri bunu çok kolay bir şekilde entegre edebilmemizi sağlamışlar.

Blazor’un Genel Mimarisi Aşağıdaki Gibidir

Aşağıdaki görüntü Chrome’daki bir Blazor uygulamasının önyükleme işlemini göstermektedir. Uygulama Blazor JavaScript ( blazor.js ) içerir. Mono çalışma zamanını ( mono.wasm ) WebAssembly içinde önyüklemek için Mono’nun JavaScript kitaplığını ( mono.js ) kullanır. Daha sonra uygulamanın DLL dosyasını ( WebApplication2.dll ) ve .NET Framework’ün DLL’lerini yükler .

K

.NET CORE 3.0 yeniliklerini inceleyelim.

Windows Desktop Desteği

Artık .net core ile Desktop uygulamları yazılabilecek.
WPF, Windows formları ve WinUI artık açık kaynaklı olacak.

Newtonsoft  Geliyor

Anladığım kadarı ile Microsoft kendi Json reader’ının yavaş olduğunu fark etti. Kendisinden daha performanslı olduğunu kanıtlayan Newtonsoft u default olarak kullanacak.

Index Sınıfı

Index tipi eklendi. Artık int kullanmak zorunda değiliz. Index tipinin amacı tuttuğumuz değere dizinin neresinden başlayacağını atayabiliriz.

Index i1 = 2;  // 2. index den başla
Index i2 = ^3; // 3. adım ilerle
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "2, 5"

Range Sınıfı

Typescript’ten aşina olduğumuz bir kullanım şekli aslında. Range ise iki Index kullanarak dizinin belirli bir kısmını ifade edebileceğimiz bir yapı.
a dizisi içerisinde i1 ve i2 Index leri arasını range ile alabiliyoruz.


int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var slice = a[i1..i2]; // { 3, 4, 5 }

Kaynak