MVC ASP.NET Core geliştirme

"İlk kez doğru şekilde elde etmek önemli değildir. Bunu en son doğru şekilde yapmak çok önemlidir." - Andrew Hunt ve David Thomas

ASP.NET Core, modern bulut için iyileştirilmiş web uygulamaları için platformlar arası, açık kaynak bir çerçevedir. ASP.NET Core basit ve modülerdir ve bağımlılık eklemeye yönelik yerleşik destek sayesinde daha fazla test ve bakım sağlar. Görünüm tabanlı uygulamaların yanı sıra modern web API'leri derlemeyi destekleyen MVC ile birlikte ASP.NET Core, kurumsal web uygulamaları oluşturmak için güçlü bir çerçevedir.

MVC ve Razor Pages

ASP.NET Core MVC, web tabanlı API'ler ve uygulamalar için kullanışlı olan birçok özellik sunar. MVC terimi, kullanıcı isteklerine yanıt verme sorumluluklarını birkaç parçaya dönüştüren bir kullanıcı arabirimi deseni olan "Model-View-Controller" terimini ifade eder. Bu düzenin yanı sıra, ASP.NET Core uygulamalarınıza Razor Pages. Razor Pages MVC'ASP.NET Core yerleşiktir ve yönlendirme, model bağlama, filtreler, yetkilendirme vb. için aynı özellikleri kullanır. Ancak, Denetleyiciler, Modeller, Görünümler vb. için ayrı klasörlere ve dosyalara sahip olmak ve öznitelik tabanlı yönlendirme kullanmak yerine Razor Pages tek bir klasöre ("/Sayfalar") yerleştirilir, bu klasördeki göreli konumlarına göre yol oluşturur ve istekleri denetleyici eylemleri yerine işleyicilerle işleyicilerle işler. Sonuç olarak, Razor Pages, ihtiyacınız olan tüm dosyalar ve sınıflar genellikle birlikte birlikte yer alan bir web projesine yayılmaz.

Yeni bir ASP.NET Core Uygulaması 7.000.000.000'den önce oluşturmak istediğiniz uygulamanın nasıl olduğunu planlasanız iyi olur. Bu Visual Studio birkaç şablondan birini seçebilirsiniz. En yaygın üç proje şablonu Web API'si, Web Uygulaması ve Web Uygulamasıdır (Model-View-Controller). Bu kararı yalnızca projeyi ilk oluşturma adımında ve ancak geri dönülemez bir kararla atayamazsiniz. Web API'si projesi standart Model-View-Controller denetleyicilerini kullanır; yalnızca varsayılan olarak Görünümler'den eksiktir. Benzer şekilde, varsayılan Web Uygulaması şablonu Razor Pages kullanır ve bu nedenle bir Görünümler klasörü de eksiktir. Görünüm tabanlı davranışı desteklemek için daha sonra bu projelere bir Görünümler klasörü ekebilirsiniz. Web API'si ve Model-View-Controller projeleri varsayılan olarak bir Pages klasörü içermemektedir, ancak daha sonra, sayfa tabanlı davranışı desteklemek için Razor Pages bir klasör eklersiniz. Bu üç şablonu, üç farklı tür varsayılan kullanıcı etkileşimini destekleyen bir şablon olarak düşünebilirsiniz: veriler (web API'si), sayfa tabanlı ve görünüm tabanlı. Ancak isterseniz tek bir proje içinde bu şablonların herhangi birini veya hepsini karıştırıp eşlersiniz.

Neden Razor Pages?

Razor Pages, yeni web uygulamaları için varsayılan yaklaşımdır Visual Studio. Razor Pages SPA dışı formlar gibi sayfa tabanlı uygulama özelliklerini daha basit bir şekilde oluşturur. Denetleyiciler ve görünümler kullanılarak, uygulamaların birçok farklı bağımlılıkla çalışan ve modelleri görüntüleyen ve birçok farklı görünümde döndürülen çok büyük denetleyicileri olması yaygındı. Bu durum daha karmaşık hale geldi ve genellikle Tek Sorumluluk İlkesini veya Açık/Kapalı İlkeleri etkili bir şekilde izlemedi. Razor Pages razor işaretlemesi ile bir web uygulamasındaki verilen mantıksal "sayfa" için sunucu tarafı mantığını kapsülleerek bu sorunu giderebilirsiniz. Sunucu tarafı mantığı olmayan bir Razor Sayfası yalnızca bir Razor dosyasından (örneğin, "Index.cshtml") oluşur. Ancak, önemsiz olmayan Razor Pages, kurala göre ".cs" uzantısına sahip Razor dosyasıyla aynı adlı ilişkili bir sayfa modeli sınıfına (örneğin, "Index.cshtml.cs") sahip olur.

Razor Sayfasının sayfa modeli, MVC denetleyicisinin ve viewmodel'in sorumluluklarını birleştirir. "OnGet()" gibi sayfa modeli işleyicileri, istekleri denetleyici eylem yöntemleriyle işleme yerine yürütülür ve varsayılan olarak ilişkili sayfası görüntülenir. Razor Pages, MVC'nin tüm mimari özelliklerini sağlarken bir ASP.NET Core uygulama içinde tek tek sayfa ASP.NET Core kolaylaştırır. Bunlar, yeni sayfa tabanlı işlevler için iyi bir varsayılan seçenektir.

MVC ne zaman kullanımlı?

Web API'leri Razor Pages. Projeniz yalnızca web API'si uç noktalarını gösterirse, ideal olarak Web API proje şablonundan başlamanız gerekir. Aksi takdirde, herhangi bir uygulama için denetleyiciler ve ilişkili API uç noktaları ASP.NET Core kolaydır. Var olan bir uygulamayı ASP.NET MVC 5 veya önceki bir sürümden ASP.NET Core MVC'ye ASP.NET Core kullanıyorsanız ve bunu en az çabayla yapmak için görünüm tabanlı MVC yaklaşımını kullanın. İlk geçişi gerçekleştirip yeni özelliklere veya toplu geçişe Razor Pages uygun olup olmadığını değerlendirin.

Web uygulamalarınızı Razor Pages veya MVC görünümlerini kullanarak derlemeyi tercih ediyorsanız, uygulamanız benzer performansa sahip olur ve bağımlılık ekleme, filtreler, model bağlama, doğrulama gibi destek içerir.

İstekleri yanıtlara eşleme

Bu uygulamaların ASP.NET Core istekleri giden yanıtlara eşlemesini sağlar. Düşük düzeyde, bu eşleme ara yazılım ile yapılır ve basit ASP.NET Core uygulamaları ve mikro hizmetleri yalnızca özel ara yazılımdan oluşsa. MVC ASP.NET Core kullanırken rotalar, denetleyiciler ve eylemler bakımından daha yüksek bir düzeyde çalışabilirsiniz. Gelen her istek, uygulamanın yönlendirme tablosuyla karşılaştırıldı ve eşleşen bir yol bulunursa, isteği işlemek için ilişkili eylem yöntemi (denetleyiciye ait) çağrılır. Eşleşen bir yol bulunamasa, bir hata işleyicisi (bu durumda, bir NotFound sonucu döndürerek) çağrılır.

ASP.NET Core MVC uygulamaları geleneksel yolları, öznitelik yollarını veya her ikisini birden kullanabilir. Geleneksel yollar, aşağıdaki örnekte olduğu gibi söz dizimi kullanılarak yönlendirme kuralları belirterek kodda tanımlanır:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});

Bu örnekte yönlendirme tablosuna "default" adlı bir yol eklenmiştir. , ve için yer tutucuları olan bir controller yol action şablonu id tanımlar. ve yer tutucuları varsayılan olarak belirtilir ( sırasıyla ve ) ve yer tutucu isteğe bağlıdır controller action Home Index id (buna bir "?" uygulandığı için). Burada tanımlanan kural, isteğin ilk kısmının denetleyicinin adına, ikinci kısmı eyleme karşılık gel gerektiğini belirtir ve gerekirse üçüncü bölüm bir kimlik parametresini temsil eder. Geleneksel yollar genellikle uygulama için sınıfındaki yönteminde olduğu gibi tek Configure bir yerde Startup tanımlanır.

Öznitelik yolları, genel olarak belirtilmezse denetleyicilere ve eylemlere doğrudan uygulanır. Bu yaklaşım, belirli bir yönteme bakarak bunları çok daha kolay keşfedilebilir yapma avantajına sahip olur, ancak yönlendirme bilgileri uygulamada tek bir yerde tutulmaz. Öznitelik yolları ile belirli bir eylem için kolayca birden çok yol belirtebilir ve denetleyicilerle eylemler arasındaki yolları birleştirebilirsiniz. Örnek:

[Route("Home")]
public class HomeController : Controller
{
    [Route("")] // Combines to define the route template "Home"
    [Route("Index")] // Combines to define route template "Home/Index"
    [Route("/")] // Does not combine, defines the route template ""
    public IActionResult Index() {}
}

Yollar [HttpGet] ve benzer özniteliklerde belirtilebilir ve ayrı [Route] öznitelikleri ekleme ihtiyacının önüne geçilebilir. Öznitelik yolları, aşağıda gösterildiği gibi denetleyici veya eylem adlarını yineleme ihtiyacının azaltılması için belirteçleri de kullanabilir:

[Route("[controller]")]
public class ProductsController : Controller
{
    [Route("")] // Matches 'Products'
    [Route("Index")] // Matches 'Products/Index'
    public IActionResult Index() {}
}

Razor Pages öznitelik yönlendirmesi kullanmaz. Bir Razor Sayfası için ek yol şablonu bilgilerini yönergesi kapsamında @page belirtebilirsiniz:

@page "{id:int}"

Önceki örnekte, söz konusu sayfa tamsayı parametresine sahip bir yol ile eş id değerdir. Örneğin, kökünde bulunan Products.cshtml sayfasında /Pages şu yol bulunur:

"/Products/123"

Bir istek bir yol ile eşlense de eylem yöntemi çağrılmadan önce, ASP.NET Core MVC istekte model bağlama ve model doğrulaması gerçekleştirecek. Model bağlaması, gelen HTTP verilerini çağrıl yapılacak eylem yönteminin parametreleri olarak belirtilen .NET türlerine dönüştürmekle sorumludur. Örneğin, eylem yöntemi bir parametre bekliyorsa, model bağlaması isteğin bir parçası olarak sağlanan bir değerden bu int id parametreyi sağlamayı dener. Bunu yapmak için, model bağlaması gönderilen bir formda değerleri, yol içinde değerleri ve sorgu dizesi değerlerini aramaz. Bir id değerin bulunduğu varsayıldık, eylem yöntemine geçirimeden önce bir tamsayıya dönüştürülür.

Modeli bağlamanın ardından ancak eylem yöntemini çağırmadan önce model doğrulaması gerçekleşir. Model doğrulaması model türü üzerinde isteğe bağlı öznitelikler kullanır ve sağlanan model nesnesinin belirli veri gereksinimlerine uygun olduğundan emin olunmasına yardımcı olabilir. Belirli değerler gerekli olarak belirtilebilir veya belirli bir uzunluk veya sayısal aralıkla sınırlandırilebilir. Doğrulama öznitelikleri belirtilmişse ancak model gereksinimlerine uygun yoksa ModelState.IsValid özelliği false olur ve başarısız doğrulama kuralları kümesi isteği yapan istemciye gönderilebilir.

Model doğrulamayı kullanıyorsanız, durum değiştirme komutları gerçekleştirmeden önce modelin geçerli olup olmadığını mutlaka denetlemeniz ve uygulamanın geçersiz veriler tarafından bozulmasına neden olmadığını doğrulamanız gerekir. Her eylemde bu doğrulama için kod ekleme ihtiyacının önüne bir filtre kullanabilirsiniz. ASP.NET Core MVC filtreleri, ortak ilkelerin ve çapraz kesme endişelerinin hedeflenen bir şekilde uygulanamalarını sağlar. Filtreler tek tek eylemlere, tüm denetleyicilere veya bir uygulama için genel olarak uygulanabilir.

Web API'leri ASP.NET Core MVC içerik anlaşmalarını destekler ve isteklerin yanıtların nasıl biçimlendir olacağını belirtmesini sağlar. İstekte sağlanan üst bilgilere bağlı olarak, verileri döndüren eylemler yanıtı XML, JSON veya desteklenen başka bir biçimde biçimlendirecek. Bu özellik, aynı API'nin farklı veri biçimi gereksinimleri olan birden çok istemci tarafından kullanılmasını sağlar.

Web API'si projeleri tek tek denetleyicilere, bir temel denetleyici sınıfına veya bütün derlemeye uygulanacak [ApiController] özniteliğini kullanmayı göz önünde bulundurmalıdır. Bu öznitelik otomatik model doğrulama denetimi ekler ve geçersiz modele sahip herhangi bir eylem, doğrulama hatalarının ayrıntılarıyla bir BadRequest geri döner. Özniteliği ayrıca tüm eylemlerin geleneksel bir yol kullanmak yerine bir öznitelik yolu gerektirir ve hatalara yanıt olarak daha ayrıntılı ProblemDetails bilgileri döndürür.

Denetleyicileri denetim altında tutma

Sayfa tabanlı uygulamalarda, Razor Pages fazla büyük olmaya devam etmek için harika bir iş çıkarabilirsiniz. Her sayfaya yalnızca işleyicilerine ayrılmış kendi dosyaları ve sınıfları verilir. Görünüm odaklı uygulamaların Razor Pages birçok farklı eylem ve görünümden sorumlu büyük denetleyici sınıfları olurdu. Bu sınıflar doğal olarak birçok sorumluluk ve bağımlılık olacak şekilde büyüyecek ve bakımları zorlaştıracak. Görünüm tabanlı denetleyicilerinizin çok büyük olduğunu bulursanız, bunları Razor Pages kullanmak üzere yeniden düzenlemeyi veya bir aracı gibi bir desen tanıtmayı göz önünde bulundurabilirsiniz.

Arayıcı tasarım deseni, sınıflar arasındaki bağlantının azaltılması için kullanılırken bu iki sınıf arasında iletişime olanak sağlar. Bu ASP.NET Core MVC uygulamalarında, bu düzen genellikle eylem yöntemlerinin işleyicileri kullanılarak denetleyicileri daha küçük parçalara ayıracak şekilde kullanılır. Popüler MediatR NuGet paketi genellikle bunu gerçekleştirmek için kullanılır. Denetleyiciler genellikle her biri belirli bağımlılıklar gerektiren birçok farklı eylem yöntemi içerir. Herhangi bir eylem için gerekli olan tüm bağımlılıkların kümesi denetleyicinin oluşturucus una geçir gerekir. MediatR kullanırken, denetleyicinin sahip olduğu tek bağımlılık, bir aracı örneğindedir. Her eylem daha sonra bir işleyici tarafından işlenen bir ileti göndermek için aracı örneğini kullanır. İşleyici tek bir eyleme özgü olduğu için yalnızca bu eylemin gerekli olduğu bağımlılıklara ihtiyaç gösterir. MediatR kullanan bir denetleyici örneği burada gösterilmiştir:

public class OrderController : Controller
{
    private readonly IMediator _mediator;

    public OrderController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpGet]
    public async Task<IActionResult> MyOrders()
    {
        var viewModel = await _mediator.Send(new GetMyOrders(User.Identity.Name));

        return View(viewModel);
    }

    // other actions implemented similarly
}

MyOrdersEylemde, bir Send iletiye yapılan çağrı şu sınıf GetMyOrders tarafından işleme alır:

public class GetMyOrdersHandler : IRequestHandler<GetMyOrders, IEnumerable<OrderViewModel>>
{
    private readonly IOrderRepository _orderRepository;

    public GetMyOrdersHandler(IOrderRepository orderRepository)
    {
        _orderRepository = orderRepository;
    }

    public async Task<IEnumerable<OrderViewModel>> Handle(GetMyOrders request, CancellationToken cancellationToken)
    {
        var specification = new CustomerOrdersWithItemsSpecification(request.UserName);
        var orders = await _orderRepository.ListAsync(specification);

        return orders.Select(o => new OrderViewModel
        {
            OrderDate = o.OrderDate,
            OrderItems = o.OrderItems?.Select(oi => new OrderItemViewModel()
            {
                PictureUrl = oi.ItemOrdered.PictureUri,
                ProductId = oi.ItemOrdered.CatalogItemId,
                ProductName = oi.ItemOrdered.ProductName,
                UnitPrice = oi.UnitPrice,
                Units = oi.Units
            }).ToList(),
            OrderNumber = o.Id,
            ShippingAddress = o.ShipToAddress,
            Total = o.Total()
        });
    }
}

Bu yaklaşımın sonucu, denetleyicilerin çok daha küçük olması ve öncelikli olarak yönlendirme ve model bağlamaya odaklanması, tek tek işleyicilerin belirli bir uç nokta için gereken belirli görevlerden sorumlu olmasıdır. Bu yaklaşım, ApiEndpoints NuGetpaketi kullanılarak MediatR olmadan da elde edilebilir. Bu paket, API denetleyicilerine görünüm tabanlı denetleyiciler için Razor Pages avantajları getirir.

Başvurular – İstekleri Yanıtlara Eşleme

Bağımlılıklarla çalışma

ASP.NET Core yerleşik desteği vardır ve bağımlılık ekleme olarak bilinen bir tekniği dahili olarak kullanır. Bağımlılık ekleme, bir uygulamanın farklı bölümleri arasında gevşek bağlantı sağlayan bir tekniktir. Uygulamanın parçalarını yalıtarak test veya değiştirmeye olanak sağlayan gevşek eşleştirme tercih edilir. Ayrıca uygulamanın bir bölümünde yapılan bir değişikliğin uygulamanın başka bir bölümünde beklenmedik bir etkisi olması da olasıdır. Bağımlılık ekleme, bağımlılık ters çevirme ilkesine dayalıdır ve genellikle açık/kapalı ilkeyi elde etmek için anahtardır. Uygulamanın bağımlılıkları ile nasıl çalıştığını değerlendirirken statik cling koduna dikkat edin ve"new is glue"(yeni birleştiricidir)forluğunu unutmayın.

Statik cling, sınıflarınız statik yöntemlere çağrılar yaptıklarında veya altyapı üzerinde yan etkileri veya bağımlılıkları olan statik özelliklere eriştikleri zaman oluşur. Örneğin, statik bir yöntemi çağıran bir yönteminiz varsa ve bu yöntem veritabanına yazarsa, yönteminiz veritabanıyla sıkı bir şekilde bağlı olur. Bu veritabanı çağrısını bozan her şey yönteminizi bozar. Statik çağrıları taklit etmek için ticari sahte kitaplıklar gerektirmesi veya yalnızca yerinde bir test veritabanıyla test edilebilir olması nedeniyle bu tür yöntemleri test etmek oldukça zordur. Özellikle durum bilgisiz çağrılar olmak üzere altyapıya herhangi bir bağımlılığı olmayan statik çağrılar çağrılabilir ve bağlama veya test sınanabilirlik üzerinde herhangi bir etkisi olmaz (kodu statik çağrının kendisiyle eşleştirmenin ötesinde).

Birçok geliştirici statik cling ve genel durum risklerini anlar, ancak yine de doğrudan örnekleme aracılığıyla kendi kodunu belirli uygulamalarla sıkı bir şekilde bir şekilde birlemektedir. "Yeni birleştiricidir", anahtar sözcüğünün kullanımına genel bir açıklama değil, bu eşlemenin anımsatıcısı olarak new ifade etmektir. Statik yöntem çağrılarının olduğu gibi, dış bağımlılıkları olmayan yeni tür örnekleri genellikle kodu uygulama ayrıntılarıyla sıkı bir şekilde bağlanmaz veya testi daha zor hale geçirmez. Ancak, bir sınıfın örneği her kez örneği esnetilen her durumda, bu belirli bir örneği belirli bir konumda sabit olarak koda kodun sabit olarak koda konma veya bu örneği bağımlılık olarak istemenin daha iyi bir tasarım olup olmadığını düşünmek için yalnızca kısa bir dakika zaman alır.

Bağımlılıklarınızı bildir

ASP.NET Core yöntemlerin ve sınıfların bağımlılıklarını bildirerek bağımsız değişken olarak istekte bulundurarak yerleşik olarak yer almaktadır. ASP.NET uygulamalar genellikle başlangıç sınıfında ayarlanır ve bu sınıf kendisini çeşitli noktalarda bağımlılık eklemeyi destekleyecek şekilde yapılandırılmıştır. Başlangıç sınıfınız bir oluşturucuya sahipse, oluşturucu aracılığıyla bağımlılıkları şu şekilde talep eder:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
    }
}

Başlangıç sınıfı, bunun için açık tür gereksinimlerinin olmadığını ilgi çekicidir. Özel bir Başlangıç temel sınıfından devralmaz ve belirli bir arabirimi uygulamaz. Oluşturucuya bir oluşturucu veya değil ve istediğiniz sayıda parametre belirtebilirsiniz. Uygulamanız için yapılandırmış olduğu web ana bilgisayarı başlatıldığında, bunu kullanmasını söyledik Startup sınıfını çağıracak ve Başlangıç sınıfının gerektirdiği tüm bağımlılıkları doldurmak için bağımlılık ekleme kullanır. Elbette ASP.NET Core tarafından kullanılan hizmetler kapsayıcısı içinde yapılandırılmamış parametreler isteğinde bulunduysanız bir özel durumla karşı karşılayabilirsiniz ancak kapsayıcının bildiği bağımlılıklara bağlı kalarak istediğiniz her şeyi isteğinde bulundurabilirsiniz.

Bağımlılık ekleme, başlangıç ASP.NET Core en baştan uygulamanıza yerleşik olarak yerleşiktir. Başlangıç sınıfı için orada durmaz. Ayrıca Configure yönteminde bağımlılık isteğinde de kullanabilirsiniz:

public void Configure(IApplicationBuilder app,
    IHostingEnvironment env,
    ILoggerFactory loggerFactory)
{

}

ConfigureServices yöntemi bu davranışın özel durumudur; IServiceCollection türünde yalnızca bir parametre al olmalıdır. Bağımlılık eklemeyi desteklemesi gerekmemektedir, bir yandan hizmet kapsayıcısı nesnelerini eklemekle sorumludur, diğer yandan da IServiceCollection parametresi aracılığıyla o anda yapılandırılmış olan tüm hizmetlere erişimi vardır. Bu nedenle, gerekli hizmeti parametre olarak isteğinde bulundurarak veya ConfigureServices'te IServiceCollection ile çalışarak Başlangıç sınıfının her bölümünde ASP.NET Core hizmetleri koleksiyonunda tanımlanan bağımlılıklarla çalışabilirsiniz.

Not

Startup sınıfınız için belirli hizmetlerin kullanılabilir olduğundan emin olmak gerekirse, CreateDefaultBuilder çağrısında bir IWebHostBuilder ve onun ConfigureServices yöntemini kullanarak bunları yapılandırabilirsiniz.

Başlangıç sınıfı, Denetleyiciler'den Ara Yazılımdan Filtreler'e ve kendi Hizmetlerinize kadar ASP.NET Core uygulama uygulamanın diğer bölümlerini nasıl yapılandırmanız gerektiğine bir modeldir. Her durumda, doğrudan oluşturmak yerine bağımlılıklarınızı talep etmek ve uygulamanız genelinde bağımlılık eklemeden yararlanarak Açık Bağımlılıklar İlkesi'ne uymanız gerekir. Özellikle altyapıyla birlikte çalışmakta olan veya yan etkileri olan hizmetler ve nesneler olmak üzere uygulamaları nerede ve nasıl doğrudan örnekleyebilirsiniz? Uygulama çekirdeğinde tanımlanan ve belirli uygulama türlerine yapılan başvuruları sabit olarak kabul etmek için bağımsız değişken olarak geçirilen soyutlamalarla çalışmayı tercih eder.

Uygulamayı yapılandırma

Monolitik uygulamalar genellikle tek bir giriş noktasına sahiptir. Bir web uygulamasında ASP.NET Core noktası, web projesinin ASP.NET Core noktası olur. Ancak bu, çözümün yalnızca tek bir projeden oluşan bir çözüm olması gerektiği anlamına değildir. Endişe ayrımlarını takip etmek için uygulamayı farklı katmanlara ayırmaya yarar. Katmanlara ayırmanın ardından, daha iyi kapsülleme elde etmeye yardımcı olacak şekilde, projeleri ayırmak için klasörlerin ötesine gitmek yararlı olur. ASP.NET Core uygulamasıyla bu hedeflere ulaşmak için en iyi yaklaşım, 5. bölümde ele alınmıştır. Bu yaklaşımın ardından, uygulamanın çözümü kullanıcı arabirimi, Altyapı ve ApplicationCore için ayrı kitaplıklardan oluşur.

Bu projelere ek olarak ayrı test projeleri de dahil edilir (Test, 9. Bölümde ele alınmıştır).

Uygulamanın nesne modeli ve arabirimleri ApplicationCore projesine yerleştiril olmalı. Bu projenin mümkün olduğunca az bağımlılığı olur ve çözümdeki diğer projeler buna başvurur. Kalıcı olması gereken iş varlıkları, altyapıya doğrudan bağımlı olan hizmetler gibi ApplicationCore projesinde tanımlanır.

Kalıcılık nasıl gerçekleştiriliyor veya bir kullanıcıya nasıl bildirim gönderiliyor gibi uygulama ayrıntıları Altyapı projesinde tutulur. Bu proje, Entity Framework Core gibi uygulamaya özgü paketlere başvurur, ancak bu uygulamalarla ilgili ayrıntıları projenin dışında açığa çıkarmaz. Altyapı hizmetleri ve depoları, ApplicationCore projesinde tanımlanan arabirimleri uygulamalı ve kalıcılık uygulamaları ApplicationCore'da tanımlanan varlıkları almak ve depolamakla sorumludur.

Kullanıcı ASP.NET Core kullanıcı arabirimi projesi tüm kullanıcı arabirimi düzeyinde sorunlardan sorumludur, ancak iş mantığı veya altyapı ayrıntılarını içermesi gerekir. Aslında ideal olan, Altyapı projesine bile bağımlılık olmamasıdır. Bu da iki proje arasında yanlışlıkla bağımlılık olmamasına yardımcı olur. Bu, her projede Modül sınıflarında DI kuralları tanımlamaya olanak sağlayan Autofac gibi bir üçüncü taraf DI kapsayıcısı kullanılarak elde edilebilir.

Uygulamayı uygulama ayrıntılarından ayrı yapmaya yönelik bir diğer yaklaşım da uygulamanın mikro hizmetleri çağırması ve belki de tek tek Docker kapsayıcılarında dağıtılmasıdır. Bu, iki proje arasında DI'den yararlanarak daha da fazla endişe ayrımı ve ayırma sağlar, ancak ek karmaşıklığa sahiptir.

Özellik kuruluşu

Varsayılan olarak, ASP.NET Core, klasör yapılarını Denetleyiciler ve Görünümler'i ve sık sık ViewModel'leri içerecek şekilde düzenleyebilir. Bu sunucu tarafı yapılarını desteklemek için istemci tarafı kodu genellikle wwwroot klasöründe ayrı olarak depolanır. Ancak, belirli bir özellik üzerinde çalışmak genellikle bu klasörler arasında geçiş gerektirdiği için büyük uygulamalar bu kuruluşta sorunlarla karşılaşabilirsiniz. Her klasördeki dosya ve alt klasör sayısı arttıkça bu durum her geçen gün daha zor hale geliyor ve bu da dosya ve klasör Çözüm Gezgini. Bu sorunun çözümlerinden biri, uygulama kodunu dosya türü yerine özel olarak düzenlemektir. Bu kuruluş stili genellikle özellik klasörleri veya özellik dilimleri olarak adlandırılır (ayrıca bkz. Dikey Dilimler).

ASP.NET Core MVC bu amaçla Alanları destekler. Alanları kullanarak, her Bir Alan klasöründe ayrı Denetleyiciler ve Görünümler klasör kümeleri (ve ilişkili modeller) oluşturabilirsiniz. Şekil 7-1'de, Alanlar kullanılarak örnek bir klasör yapısı gösterir.

Örnek Alan Kuruluşu

Şekil 7-1. Örnek Alan Kuruluşu

Alanlar'ı kullanırken, denetleyicilerinizi ait olduğu alan adıyla dekore etmek için öznitelikleri kullansanız gerekir:

[Area("Catalog")]
public class HomeController
{}

Rotalarınıza alan desteği de eklemeniz gerekir:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "areaRoute", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});

Alanlar için yerleşik deliğe ek olarak, öznitelikler ve özel yollar yerine kendi klasör yapınızı ve kuralları da kullanabilirsiniz. Bu, Görünümler, Denetleyiciler vb. için ayrı klasörlere sahip değil özellik klasörlerine sahip olur, hiyerarşiyi daha düz hale getirir ve ilgili tüm dosyaları her özellik için tek bir yerde daha kolay bir şekilde görmenizi sağlar.

ASP.NET Core davranışını kontrol etmek için yerleşik kural türlerini kullanır. Bu kuralları değiştirebilir veya değiştirebilirsiniz. Örneğin, ad alanına göre belirli bir denetleyicinin özellik adını otomatik olarak alan (genellikle denetleyicinin bulunduğu klasörle ilişkili olan) bir kural oluşturabilirsiniz:

public class FeatureConvention : IControllerModelConvention
{
    public void Apply(ControllerModel controller)
    {
        controller.Properties.Add("feature",
        GetFeatureName(controller.ControllerType));
    }

    private string GetFeatureName(TypeInfo controllerType)
    {
        string[] tokens = controllerType.FullName.Split('.');
        if (!tokens.Any(t => t == "Features")) return "";
        string featureName = tokens
        .SkipWhile(t => !t.Equals("features",
        StringComparison.CurrentCultureIgnoreCase))
        .Skip(1)
        .Take(1)
        .FirstOrDefault();
        return featureName;
    }
}

Ardından Bu kuralı, ConfigureServices'te uygulamanıza MVC desteği eklerken bir seçenek olarak belirtirsiniz:

services.AddMvc(o => o.Conventions.Add(new FeatureConvention()));

ASP.NET Core MVC ayrıca görünümleri bulmak için bir kural kullanır. Görünümlerin özellik klasörlerinize yerleştirilebilir (yukarıda FeatureConvention tarafından sağlanan özellik adını kullanarak) bu özelliği özel bir kuralla geçersiz kılabilirsiniz. Bu yaklaşım hakkında daha fazla bilgi edinebilirsiniz ve MVC için Msdn Magazine Özellik Dilimleri makalesinde ASP.NET Core indirebilirsiniz.

API'ler ve Blazor uygulamalar

Uygulamanıza güvenliği sağlanacak bir dizi web API'si varsa, bu API'ler ideal olarak Görünüm veya uygulama uygulamanıza göre ayrı bir proje olarak Razor Pages gerekir. ÖZELLIKLE genel API'ler olmak üzere API'leri sunucu tarafı web uygulamanıza ayırmak bir dizi avantaj sunar. Bu uygulamalar genellikle benzersiz dağıtım ve yük özelliklerine sahip olur. Ayrıca tanımlama bilgisi tabanlı kimlik doğrulamasından ve belirteç tabanlı kimlik doğrulaması kullanan API'lerden yararlanarak standart form tabanlı uygulamalarla farklı güvenlik mekanizmalarını benimseme olasılığı da yüksek olur.

Buna ek Blazor olarak, Sunucu veya Blazor kullanan uygulamalar ayrı projeler olarak inşa Blazor WebAssembly edilecektir. Uygulamaların çalışma zamanı özelliklerinin yanı sıra güvenlik modelleri de farklıdır. Ortak türleri sunucu tarafı web uygulamasıyla (veya API projesiyle) paylaşabilirler ve bu türler ortak bir paylaşılan projede tanımlanmalıdır.

Blazor WebAssembly eShopOnWeb'e yönetici arabiriminin ek olarak birkaç yeni proje eklemesi gerekir. Projenin Blazor WebAssembly kendisi, BlazorAdmin . tarafından kullanılan ve belirteç tabanlı kimlik doğrulaması kullanmak üzere yapılandırılmış yeni bir genel API BlazorAdmin uç noktaları kümesi projede PublicApi tanımlanır. Ve bu projelerin her ikisi tarafından kullanılan bazı paylaşılan türler yeni bir BlazorShared projede tutulur.

Bunlardan biri, BlazorShared ApplicationCore hem hem de gereken herhangi bir türü paylaşmak için kullanılabilen ortak bir proje olduğunda PublicApi , neden tek bir proje eklemeli, neden olabilir. BlazorAdmin Yanıt, bu projenin tüm uygulamanın iş mantığını içermesi ve bu nedenle gerekenden çok daha büyük olması ve sunucuda güvenli tutulması gereken çok daha fazla olasılıktır. Tarafından başvurulan herhangi bir kitaplığın BlazorAdmin , uygulamayı yüklediklerinde kullanıcıların tarayıcılarına indirileceğini unutmayın Blazor .

Arka uçlar-for-frontends (BFF) modelinikullanıp kullanmadığını bağlı olarak, uygulama tarafından tüketilen API 'ler Blazor WebAssembly ile %100 türlerini paylaşamaz Blazor . Özellikle, birçok farklı istemci tarafından kullanılması amaçlanan ortak bir API, istemciye özgü paylaşılan bir projede paylaşmak yerine kendi istek ve sonuç türlerini tanımlayabilir. EShopOnWeb örneğinde, PublicApi Proje bir ortak API barındırılmakta olduğundan, tüm istek ve yanıt türleri projeden gelmemesi için varsayım yapılır BlazorShared .

Geniş kapsamlı kritik konular

Uygulamalar büyüdükçe, çoğaltmayı ortadan kaldırmak ve tutarlılığı sürdürmek için çapraz kesme sorunlarını ortadan kaldırmak giderek daha da önemli hale gelir. ASP.NET Core uygulamalardaki çapraz kesme kaygılarının bazı örnekleri, çok sayıda diğerleri olsa da, kimlik doğrulama, model doğrulama kuralları, çıktı önbelleği ve hata işleme örnekleridir. ASP.NET Core MVC filtreleri istek işleme ardışık düzeninde belirli adımlardan önce veya sonra kod çalıştırmanızı sağlar. Örneğin bir filtre, model bağlamadan önce ve sonra, bir eylemden önce ve sonra ya da bir eylem sonucundan önce ve sonra çalışabilir. Ayrıca, ardışık düzenin geri kalanına erişimi denetlemek için bir yetkilendirme filtresi de kullanabilirsiniz. Şekil 7-2, yapılandırılmışsa, istek yürütmenin filtreler aracılığıyla nasıl akacağını 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ü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.

Şekil 7-2. Filtreler ve istek işlem hattı aracılığıyla yürütme isteği.

Filtreler genellikle öznitelik olarak uygulanır, bu sayede bunları denetleyicilere veya eylemlere (veya genel olarak) uygulayabilirsiniz. Bu biçimde eklendiğinde, eylem düzeyinde belirtilen filtreler geçersiz kılınır veya denetleyici düzeyinde belirtilen filtrelerin üzerine inşa edildiğinde, kendilerine genel filtreleri geçersiz kılar. Örneğin, [ yol ] özniteliği denetleyiciler ve Eylemler arasındaki yolları oluşturmak için kullanılabilir. Benzer şekilde, yetkilendirme denetleyici düzeyinde yapılandırılabilir ve aşağıdaki örnekte gösterildiği gibi ayrı eylemler tarafından geçersiz kılınır:

[Authorize]
public class AccountController : Controller

{
    [AllowAnonymous] // overrides the Authorize attribute
    public async Task<IActionResult> Login() {}
    public async Task<IActionResult> ForgotPassword() {}
}

İlk yöntem olan oturum açma, denetleyici düzeyinde ayarlanan yetkilendirme filtresini geçersiz kılmak için AllowAnonymous filtresini (özniteliği) kullanır. ForgotPassword eylemi (ve AllowAnonymous özniteliği olmayan sınıfta bulunan başka bir eylem), kimliği doğrulanmış bir istek gerektirir.

Filtreler, API 'Ler için ortak hata işleme ilkeleri biçimindeki yinelemeyi ortadan kaldırmak için kullanılabilir. Örneğin, tipik bir API ilkesi, var olmayan anahtarlara başvuran isteklere NotFound yanıtı ve model doğrulaması başarısız olursa bir BadRequest yanıtı döndürmemelidir. Aşağıdaki örnek, bu iki ilkeyi eylemde gösterir:

[HttpPut("{id}")]
public async Task<IActionResult> Put(int id, [FromBody]Author author)
{
    if ((await _authorRepository.ListAsync()).All(a => a.Id != id))
    {
        return NotFound(id);
    }
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    author.Id = id;
    await _authorRepository.UpdateAsync(author);
    return Ok();
}

Eylem yöntemlerinizi bunun gibi koşullu kodla karışık hale gelmesine izin vermez. Bunun yerine, ilkeleri gereken şekilde uygulanabilecek filtrelere çekin. Bu örnekte, API 'ye bir komutun gönderilmesi her zaman oluşması gereken model doğrulama denetimi aşağıdaki öznitelikle değiştirilebilir:

public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }
}

ValidateModelAttribute ardalış. validatemodel paketini dahil ederek projenize NuGet bağımlılığı olarak ekleyebilirsiniz. API 'Ler için, ApiController Bu davranışı ayrı bir filtreye gerek olmadan zorlamak için özniteliğini kullanabilirsiniz ValidateModel .

Benzer şekilde, bir filtre, bir kaydın mevcut olup olmadığını denetlemek için kullanılabilir ve eylem yürütülmeden önce bir 404 döndürebilir, bu denetimleri eylemde gerçekleştirme gereksinimini ortadan kaldırır. Ortak kuralları kullanıma aldıktan ve çözümünüzü altyapı kodu ve iş mantığını kullanıcı arabiriminden ayırmak üzere düzenledikten sonra, MVC eylem yöntemlerinizi son derece ölçülü olmalıdır:

[HttpPut("{id}")]
[ValidateAuthorExists]
public async Task<IActionResult> Put(int id, [FromBody]Author author)
{
    await _authorRepository.UpdateAsync(author);
    return Ok();
}

filtre uygulama hakkında daha fazla bilgi edinmek ve MSDN Magazine makalesinden, gerçek dünya ASP.NET Core MVC filtrelerindençalışan bir örneği indirmek için daha fazla bilgi edinebilirsiniz.

Başvurular – uygulamaları yapılandırma

Güvenlik

Web uygulamalarının güvenliğini sağlamak, çok sayıda konuyla büyük bir konudur. En temel düzeyinde güvenlik, belirli bir isteğin geldiği kişiyi öğrendiğinizden ve isteğin yalnızca gereken kaynaklara erişimi olduğundan emin olmanızı içerir. Kimlik doğrulaması, isteğin bilinen bir varlıktan geldiği kabul edilmesinin gerekip gerekmediğini görmek için, güvenilir bir veri deposundaki bir istekle girilen kimlik bilgilerini karşılaştırma işlemidir. Yetkilendirme, belirli kaynaklara erişimi kullanıcı kimliğine göre kısıtlama işlemidir. Üçüncü bir güvenlik konusu, isteklerin, en azından SSL 'nin uygulamanız tarafından kullanıldığından eminolmanız gereken üçüncü taraflar tarafından dinleyerek dinleme yaptığı isteklerden korunuyor.

Kimlik

ASP.NET Core Kimlik, uygulamanız için oturum açma işlevselliğini desteklemek için kullanabileceğiniz bir üyelik sistemidir. Bu, yerel kullanıcı hesaplarının yanı sıra Microsoft hesabı, Twitter, Facebook, Google ve daha fazlası gibi sağlayıcılardan dış oturum açma sağlayıcısı desteği için destek içerir. ASP.NET Core kimliğe ek olarak, uygulamanız windows kimlik doğrulamasını veya kimlik sunucusugibi bir üçüncü taraf kimlik sağlayıcısını kullanabilir.

ASP.NET Core Bireysel kullanıcı hesapları seçeneği işaretliyse, kimlik yeni proje şablonlarına dahil edilir. Bu şablon kayıt, oturum açma, dış oturum açma, unutulan parolalar ve ek işlevsellik için destek içerir.

Kimliği önceden yapılandırılmış olan bireysel kullanıcı hesaplarını seçin

Şekil 7-3. Kimliği önceden yapılandırılmış olan bireysel kullanıcı hesaplarını seçin.

Kimlik desteği başlangıçta, hem ConfigureServices hem de yapılandırma ' da yapılandırılır:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();
    services.AddMvc();
}

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();
    app.UseIdentity();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Useıdentity 'in configure yönteminde UseMvc 'den önce görünmesi önemlidir. ConfigureServices 'da kimlik yapılandırılırken, AddDefaultTokenProviders için bir çağrı olduğunu fark edeceksiniz. Bu, Web iletişimlerini güvenli hale getirmek için kullanılabilecek belirteçlerle hiçbir şey yapmaz, bunun yerine kullanıcıların kimliklerini onaylamasını sağlamak için SMS veya e-posta aracılığıyla kullanıcılara gönderilebilecek istekleri oluşturan sağlayıcılara başvurur.

iki öğeli kimlik doğrulamayı yapılandırma ve resmi ASP.NET Core belgelerinden dış oturum açma sağlayıcılarını etkinleştirme hakkında daha fazla bilgi edinebilirsiniz.

Kimlik Doğrulaması

Kimlik doğrulama, sisteme kimlerin eriştiğini belirleme işlemidir. önceki bölümde gösterilen ASP.NET Core kimliği ve yapılandırma yöntemleri kullanıyorsanız, uygulama içindeki bazı kimlik doğrulama varsayılanlarını otomatik olarak yapılandırır. Bununla birlikte, bu Varsayılanları el ile de yapılandırabilir veya AddEntity tarafından ayarlanmış olanları geçersiz kılabilirsiniz. Kimlik kullanıyorsanız, tanımlama bilgisi tabanlı kimlik doğrulamasını varsayılan Düzen olarak yapılandırır.

Web tabanlı kimlik doğrulamasında, genellikle bir sistem istemcisinin kimlik doğrulaması sırasında gerçekleştirilebilecek en fazla beş eylem vardır. Bunlar:

  • Denetimini. Uygulama içinde kullanmak üzere bir kimlik oluşturmak için istemci tarafından sunulan bilgileri kullanın.
  • Sına. Bu eylem, istemcinin kendilerini belirlemesini gerektirmek için kullanılır.
  • Yasaklamaz. İstemciye bir eylem gerçekleştirmekten yasaklanmış olduğunu bildirin.
  • Oturum açın. Mevcut istemciyi bir şekilde kalıcı hale getirin.
  • Oturum kapatma. İstemciyi kalıcılığı kaldırın.

Web uygulamalarında kimlik doğrulaması gerçekleştirmeye yönelik çeşitli yaygın teknikler vardır. Bunlar, şemalar olarak adlandırılır. Belirli bir düzen, Yukarıdaki seçeneklerin bazıları veya tümü için eylem tanımlar. Bazı şemalar yalnızca eylemlerin bir alt kümesini destekler ve desteklemediği işlemleri gerçekleştirmek için ayrı bir şema gerektirebilir. Örneğin, OpenId-Connect (OıDC) şeması, oturum açma veya oturum kapatma desteğini desteklemez, ancak yaygın olarak bu Kalıcılık için tanımlama bilgisi kimlik doğrulaması kullanmak üzere yapılandırılmıştır.

ASP.NET Core uygulamanızda, DefaultAuthenticateScheme yukarıda açıklanan eylemlerin her biri için isteğe bağlı özel düzenleri de yapılandırabilirsiniz. Örneğin,, DefaultChallengeScheme , DefaultForbidScheme vb. Çağırma AddIdentity<TUser,TRole> , uygulamanın çeşitli yönlerini yapılandırır ve birçok gerekli hizmeti ekler. Ayrıca, kimlik doğrulama düzenini yapılandırmak için bu çağrıyı içerir:

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
});

Bu düzenler, varsayılan olarak kimlik doğrulaması için oturum açma sayfalarında Kalıcılık ve yeniden yönlendirme için tanımlama bilgilerini kullanır. Bu şemalar, Web tarayıcıları aracılığıyla kullanıcılarla etkileşen ancak API 'Ler için önerilmeyen Web uygulamaları için uygundur. Bunun yerine, API 'Ler genellikle JWT taşıyıcı belirteçleri gibi başka bir kimlik doğrulama biçimi kullanır.

Web API 'Leri, HttpClient .NET uygulamaları ve diğer çerçevelerde eşdeğer türler gibi kod tarafından kullanılır. Bu istemciler bir API çağrısından kullanılabilir bir yanıt bekler veya varsa, sorun oluştuğunda ne olduğunu belirten bir durum kodudur. Bu istemciler bir tarayıcıdan etkileşim kurmazlar ve bir API 'nin döndürebileceği HTML 'yi işlemez veya bunlarla etkileşime girmezler. Bu nedenle, kimlik doğrulamasından geçirilmezse istemcilerinin oturum açma sayfalarına yönlendirilmesini sağlamak için API uç noktaları için uygun değildir. Başka bir düzen daha uygundur.

API 'Lerin kimlik doğrulamasını yapılandırmak için, PublicApi eShopOnWeb Reference uygulamasındaki proje tarafından kullanılan aşağıdaki gibi kimlik doğrulamasını ayarlayabilirsiniz:

services.AddAuthentication(config =>
{
    config.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
    .AddJwtBearer(config =>
    {
        config.RequireHttpsMetadata = false;
        config.SaveToken = true;
        config.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false,
            ValidateAudience = false
        };
    });

Tek bir proje içinde birden çok farklı kimlik doğrulama düzeni yapılandırmak mümkün olsa da, tek bir varsayılan düzeni yapılandırmak çok basittir. Bu nedenle, eShopOnWeb Reference uygulaması, API 'Lerini, PublicApi Web uygulamanın görünümlerini ve Razor Pages içeren ana projeden ayrı olarak kendi projesine ayırır.

Uygulamalarda kimlik doğrulaması Blazor

Blazorsunucu uygulamaları, diğer ASP.NET Core uygulamalarla aynı kimlik doğrulama özelliklerinden faydalanabilir. BlazorWebAssemblyuygulamalar, tarayıcıda çalıştırıldıklarından, yerleşik kimlik ve kimlik doğrulama sağlayıcılarını kullanamaz. BlazorWebAssemblyuygulamalar Kullanıcı kimlik doğrulama durumunu yerel olarak saklayabilir ve kullanıcıların gerçekleştirebilecekleri eylemleri belirlemek için taleplere erişebilir. Ancak, Blazor WebAssembly Kullanıcılar uygulamayı kolayca atlayıp API 'lerle doğrudan etkileşime girebileceği için tüm kimlik doğrulama ve yetkilendirme denetimleri, uygulamanın içinde uygulanan mantığa bakılmaksızın sunucuda gerçekleştirilmelidir.

Başvurular – kimlik doğrulaması

Yetkilendirme

En basit yetkilendirme biçimi anonim kullanıcılara erişimin kısıtlanmasını içerir. Bu işlevsellik, [ ] belirli denetleyicilere veya eylemlere Yetkilendir özniteliği uygulanarak elde edilebilir. Roller kullanılıyorsa, bu öznitelik, aşağıda gösterildiği gibi belirli rollere ait kullanıcılara erişimi kısıtlamak için daha fazla genişletilebilir.

[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{

}

Bu durumda, HRManager veya Finance rollerine (ya da her ikisine) ait olan kullanıcıların SalaryController erişimi olur. Bir kullanıcının birden çok role (yalnızca birkaç tane değil) ait olmasını gerektirmek için, her seferinde gerekli bir rol belirterek özniteliği birden çok kez uygulayabilirsiniz.

Birçok farklı denetleyicilerde ve eylemlerdeki belirli rol kümelerini belirtme, istenmeyen bir tekrarya yol açabilir. En azından, bu dize sabit değerleri için sabitleri tanımlayın ve dizeyi belirtmeniz gereken her yerde sabitleri kullanın. Yetkilendirme kurallarını kapsülleyen yetkilendirme ilkelerini de yapılandırabilir ve sonra Yetkilendir özniteliği uygulanırken ayrı roller yerine ilkeyi belirtebilirsiniz [ ] :

[Authorize(Policy = "CanViewPrivateReport")]
public IActionResult ExecutiveSalaryReport()
{
    return View();
}

İlkeleri bu şekilde kullanarak, bu işlem için uygulanan belirli rol veya kurallardan sınırlandırılmakta olan eylemlerin türlerini ayırabilirsiniz. Daha sonra, belirli kaynaklara erişmesi gereken yeni bir rol oluşturursanız, her yetkilendirme özniteliğinde her rol listesini güncelleştirmek yerine yalnızca bir ilkeyi güncelleştirebilirsiniz [ ] .

Talepler

Talepler, kimliği doğrulanmış bir kullanıcının özelliklerini temsil eden ad değer çiftleridir. Örneğin, kullanıcıların çalışan numarasını bir talep olarak saklayabilirsiniz. Talepler, yetkilendirme ilkelerinin bir parçası olarak kullanılabilir. Bu örnekte gösterildiği gibi "EmployeeNumber" adlı bir talebin varlığını gerektiren "EmployeeOnly" adlı bir ilke oluşturabilirsiniz:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });
}

Bu ilke daha sonra [ ] yukarıda açıklandığı gibi herhangi bir denetleyiciyi ve/veya eylemi korumak için yetkilendir özniteliğiyle birlikte kullanılabilir.

Web API 'Lerinin güvenliğini sağlama

Çoğu Web API 'si, belirteç tabanlı bir kimlik doğrulama sistemi uygulamalıdır. Belirteç kimlik doğrulaması durum bilgisiz ve ölçeklenebilir olacak şekilde tasarlandı. Belirteç tabanlı bir kimlik doğrulama sisteminde, istemci ilk olarak kimlik doğrulama sağlayıcısıyla kimlik doğrulaması yapması gerekir. Başarılı olursa, istemciye yalnızca şifreli olarak anlamlı bir karakter dizesi olan bir belirteç verilir. Belirteçler için en yaygın biçim JSON Web Token veya JWT (genellikle "parça" olarak belirlenir). İstemcinin bir API 'ye istek vermesi gerektiğinde, bu belirteci istek üzerine bir başlık olarak ekler. Sunucu daha sonra isteği tamamlamadan önce istek üstbilgisinde bulunan belirteci doğrular. Şekil 7-4 bu işlemi gösterir.

TokenAuth

Şekil 7-4. Web API 'Leri için belirteç tabanlı kimlik doğrulaması.

Kendi kimlik doğrulama hizmetinizi oluşturabilir, Azure AD ve OAuth ile tümleştirilebilir veya IdentityServergibi açık kaynaklı bir aracı kullanarak bir hizmet uygulayabilirsiniz.

JWT belirteçleri Kullanıcı hakkında, istemci veya sunucu üzerinde okunabilen talepler ekleyebilir. Bir JWT belirtecinin içeriğini görüntülemek için JWT.io gibi bir araç kullanabilirsiniz. İçerikleri kolayca okunduğundan, gizli verileri JTW belirteçlerinde parolalar veya anahtarlar gibi depolamayın.

SPA belirteçlerini SPA veya Blazor WebAssembly uygulamalarla kullanırken, belirteci istemcide bir yere depolamanız ve sonra her API çağrısına eklemeniz gerekir. Aşağıdaki kodun gösterdiği gibi bu etkinlik genellikle üst bilgi olarak yapılır:

// AuthService.cs in BlazorAdmin project of eShopOnWeb
private async Task SetAuthorizationHeader()
{
    var token = await GetToken();
    _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}

Yukarıdaki yöntemi çağırdıktan sonra, ile yapılan isteklere _httpClient isteğin üst bilgilerine gömülü ve sunucu tarafı API 'sinin istek için kimlik doğrulaması yapmasına ve yetkilendirilemez.

Özel Güvenlik

Özellikle şifreleme, Kullanıcı üyeliği veya belirteç oluşturma sisteminin "kendi kendine alınması" konusunda dikkatli olun. Çok sayıda ticari ve açık kaynaklı alternatif vardır ve bu, bir özel uygulamadan daha iyi güvenliğe sahip olur.

Başvurular – güvenlik

İstemci iletişimi

web apı 'leri aracılığıyla sayfalara hizmet vermeye ve veri isteklerine yanıt vermeye ek olarak, ASP.NET Core uygulamalar doğrudan bağlantılı istemcilerle iletişim kurabilir. Bu giden iletişim, en yaygın WebSockets olmak üzere çeşitli taşıma teknolojileri kullanabilir. ASP.NET Core SignalR, uygulamalarınıza gerçek zamanlı sunucudan istemciye iletişim işlevselliği eklemeyi basit hale getiren bir kitaplıktır. SignalR, WebSockets dahil olmak üzere çeşitli taşıma teknolojilerini destekler ve geliştiriciden birçok uygulama ayrıntılarını soyutlar.

WebSockets doğrudan veya diğer tekniklerin kullanılması halinde gerçek zamanlı istemci iletişimi, çeşitli uygulama senaryolarında yararlı olur. Bazı örnekler:

  • Canlı sohbet odası uygulamaları

  • Uygulamaları izleme

  • İş ilerleme durumu güncelleştirmeleri

  • Bildirimler

  • Etkileşimli form uygulamaları

Uygulamalarınıza istemci iletişimi oluştururken genellikle iki bileşen vardır:

  • Sunucu tarafı bağlantı Yöneticisi (SignalR hub, WebSocketManager WebSocketHandler)

  • İstemci tarafı kitaplığı

İstemciler tarayıcılarla sınırlı değildir: mobil uygulamalar, konsol uygulamaları ve diğer yerel uygulamalar, SignalR/WebSockets kullanarak da iletişim kurabilir. Aşağıdaki basit program, bir sohbet uygulamasına gönderilen tüm içeriği bir WebSocketManager örnek uygulamasının bir parçası olarak konsola bildirir:

public class Program
{
    private static Connection _connection;
    public static void Main(string[] args)
    {
        StartConnectionAsync();
        _connection.On("receiveMessage", (arguments) =>
        {
            Console.WriteLine($"{arguments[0]} said: {arguments[1]}");
        });
        Console.ReadLine();
        StopConnectionAsync();
    }

    public static async Task StartConnectionAsync()
    {
        _connection = new Connection();
        await _connection.StartConnectionAsync("ws://localhost:65110/chat");
    }

    public static async Task StopConnectionAsync()
    {
        await _connection.StopConnectionAsync();
    }
}

Uygulamalarınızın istemci uygulamalarıyla doğrudan iletişim kurmasına dikkat edin ve gerçek zamanlı iletişimin uygulamanızın kullanıcı deneyimini iyileştirip geliştirmeyeceğini göz önünde bulundurun.

Başvurular – Istemci Iletişimi

Etki alanı odaklı tasarım – uygulamanız gerekir mi?

Domain-Driven tasarımı (DDD), iş etki alanı üzerinde odaklanan bir yazılım oluşturmaya yönelik çevik bir yaklaşımdır. Gerçek dünya sisteminin nasıl çalıştığı geliştiricilerle ilişkilendirilebilen iş etki alanı uzmanlarındaki iletişim ve etkileşime yönelik ağır bir vurgu koyar. Örneğin, hisse senedi ilgilenen bir sistem oluşturuyorsanız, etki alanı uzmanı deneyimli bir hisse senedi Aracısı olabilir. DDD, büyük ve karmaşık iş sorunlarına yönelik olarak tasarlanmıştır ve genellikle daha küçük, daha basit uygulamalar için uygun değildir. bu da, etki alanının anlaşılmasından ve modellenmesi için yatırım yapın.

Bir DDD yaklaşımına göre yazılım oluştururken ekibiniz (Teknik olmayan hissedarlar ve katkıda bulunanlar dahil), sorun alanı için bir ubititous dili geliştirmelidir. Diğer bir deyişle, modellenen gerçek dünya kavramı, yazılım eşdeğeri ve kavramı kalıcı hale getirmek için mevcut olabilecek tüm yapılar için aynı terminoloji kullanılmalıdır (örneğin, veritabanı tabloları). Bu nedenle, ubititous dilinde açıklanan kavramlar, etki alanı modelinizin temelini oluşturmalıdır.

Etki alanı modeliniz, sistemin davranışını temsil eden birbirleriyle etkileşim kuran nesneler içerir. Bu nesneler aşağıdaki kategorilere ayrılabilir:

  • Varlıklar, bir kimlik iş parçacığına sahip nesneleri temsil eder. Varlıklar genellikle daha sonra alınabilebilecekleri bir anahtarla kalıcı olarak depolanır.

  • Birim olarak kalıcı olması gereken nesne gruplarını temsil eden toplamalar.

  • Değer nesneleri, özellik değerlerinin toplamının temel alınarak karşılaştırılabilen kavramları temsil eder. Örneğin, bir başlangıç ve bitiş tarihinden oluşan Terterange.

  • Sistem içindeki diğer bölümleri ilgilendiren işlemleri temsil eden etki alanı olayları.

DDD etki alanı modeli, model içerisindeki karmaşık davranışı kapsüllemelidir. Varlıklar, özellikle de yalnızca özellik koleksiyonları olmamalıdır. Etki alanı modelinde davranış olmadığında ve yalnızca sistemin durumunu temsil ettiğinde, bu, DDD 'da istenmeyen bir anemik modeliolarak kabul edilir.

Bu model türlerine ek olarak, DDD genellikle çeşitli desenler kullanır:

  • Depolama, kalıcılık ayrıntılarını soyutlayan.

  • Karmaşık nesne oluşturmayı kapsüllemek için fabrika.

  • Karmaşık davranışı ve/veya altyapı uygulama ayrıntılarını kapsüllemek için Hizmetler.

  • Komutu, komut veren komutları ve komutun kendisini yürütmek için.

  • Sorgu ayrıntılarını kapsüllemek için belirtimi.

DDD Ayrıca, daha önce ele alınan temiz mimarinin kullanımını önerir. böylece, birim testleri kullanılarak kolayca doğrulanabilen, gevşek bir kapsülleme, kapsülleme ve kod sağlar.

DDD ne zaman uygulanır?

DDD, önemli iş (yalnızca teknik değil) karmaşıklığa sahip büyük uygulamalar için uygundur. Uygulama, etki alanı uzmanlarının bilgisine sahip olmalıdır. Yalnızca veri depolarından çeşitli kayıtların geçerli durumunu depolamanın ve almanın ötesinde iş kurallarını ve etkileşimleri temsil eden etki alanı modelinde önemli bir davranış olmalıdır.

DDD'nin ne zaman uygulanmaması gerektiğini

DDD temelde yalnızca CRUD (oluşturma/okuma/güncelleştirme/silme) olan daha küçük uygulamalar veya uygulamalar için garanti edilecek modelleme, mimari ve iletişim yatırımları içerir. DDD'yi takip eden uygulamanıza yaklaşmayı seçerseniz ancak etki alanınız davranışsız bir anemik modele sahipse yaklaşımınızı yeniden düşünmeniz gerekir. Uygulamanıza DDD gerekmiyor veya veritabanı veya kullanıcı arabirimi yerine etki alanı modelinde iş mantığını kapsülleme konusunda yardıma ihtiyacınız olabilir.

Karma yaklaşım yalnızca uygulamanın işlemsel veya daha karmaşık alanları için DDD kullanmaktır, ancak uygulamanın daha basit CRUD veya salt okunur bölümleri için değil. Örneğin, bir raporu görüntülemek veya pano verilerini görselleştirmek için verileri sorgularsanız Toplama kısıtlamasına ihtiyacınız yok. Bu tür gereksinimler için ayrı, daha basit bir okuma modeline sahip olmak son derece kabul edilebilir.

Başvurular – Domain-Driven Tasarımı

Dağıtım

Barındırılacak yer ne olursa olsun, ASP.NET Core uygulamanızı dağıtma işleminin birkaç adımı vardır. İlk adım uygulamayı yayımlamaktır. Bu işlem CLI komutu kullanılarak dotnet publish yapılabilir. Bu adım uygulamayı derler ve uygulamayı çalıştırmak için gereken tüm dosyaları belirlenen bir klasöre yertir. Dağıtım işlemi Visual Studio bu adım sizin için otomatik olarak gerçekleştirilir. Publish klasörü, .exe ve .dll bağımlılıkları için dosyaları içerir. Kendi içinde bir uygulama da .NET çalışma zamanının bir sürümünü içerir. ASP.NET Core uygulamaları yapılandırma dosyalarını, statik istemci varlıklarını ve MVC görünümlerini de içerir.

ASP.NET Core uygulamaları, uygulama (veya sunucu) kilitleniyorsa sunucu başlatıldığında ve yeniden başlatıldığında başlatılması gereken konsol uygulamalarıdır. Bu işlemi otomatikleştirmek için bir işlem yöneticisi kullanılabilir. ASP.NET Core için en yaygın işlem yöneticileri Linux ve IIS üzerinde Nginx ve Apache veya Windows Service Windows.

İşlem yöneticisine ek olarak, ASP.NET Core uygulamalar ters ara sunucu kullanabilir. Ters ara sunucu, İnternet'den HTTP isteklerini alır ve bazı ön işlemelerden sonra bunları Kestrel'e iletir. Ters ara sunucu, uygulama için bir güvenlik katmanı sağlar. Kestrel aynı bağlantı noktası üzerinde birden çok uygulama barındırmayı da desteklemez, bu nedenle konak üst bilgileri gibi teknikler aynı bağlantı noktası ve IP adresi üzerinde birden çok uygulama barındırmayı etkinleştirmek için bu bağlantı noktasıyla kullanılamaz.

Kestrel'den İnternet'e

Şekil 7-5. ASP.NET ara sunucunun arkasındaki Kestrel'de barındırılan bir sunucu

Ters proxy'nin yararlı olduğu bir diğer senaryo da SSL/HTTPS kullanarak birden çok uygulamanın güvenliğini sağlamaktır. Bu durumda, yalnızca ters proxy'nin SSL yapılandırılmış olması gerekir. Şekil 7-6'da gösterildiği gibi, ters ara sunucu ile Kestrel arasındaki iletişim HTTP üzerinden uzamadı.

ASP.NET HTTPS ile güvenliği sağlanacak ters ara sunucu arkasında barındırılan bir sunucu

Şekil 7-6. ASP.NET HTTPS ile güvenliği sağlanacak ters ara sunucu arkasında barındırılan bir sunucu

Giderek daha popüler hale gelen bir yaklaşım, ASP.NET Core bir Docker kapsayıcısı içinde barındırmaktır. Bu kapsayıcı yerel olarak barındırılabilir veya bulut tabanlı barındırma için Azure'a dağıtılabilir. Docker kapsayıcısı, Kestrel üzerinde çalışan uygulama kodunuzu içerebilir ve yukarıda gösterildiği gibi ters proxy sunucusunun arkasında dağıtılır.

Azure'da uygulama barındırdıysanız, birkaç hizmet Microsoft Azure Application Gateway ayrılmış bir sanal gereç olarak kullanabilirsiniz. Tek tek uygulamalar için ters ara sunucu olarak davranmanın Application Gateway aşağıdaki özellikleri de sunabilirsiniz:

  • HTTP yük dengeleme

  • SSL yük boşaltma (yalnızca SSL'den İnternet'e)

  • End to End SSL

  • Çok siteli yönlendirme (tek bir sitede en fazla 20 siteyi Application Gateway)

  • Web uygulaması güvenlik duvarı

  • Websocket desteği

  • Gelişmiş tanılama

10.Bölümde Azure dağıtım seçenekleri hakkında daha fazla bilgi edinin.

Başvurular – Dağıtım